Tại sao `echo -e phiên bản \ \ SOME_TEXT '` chỉ hiển thị một dấu gạch chéo ngược?


19

Ai đó có thể giải thích những gì đang xảy ra đằng sau hậu trường trong nhân vật trốn thoát trong vỏ Linux? Tôi đã thử những điều sau đây và googled rất nhiều, mà không có bất kỳ thành công nào trong việc hiểu những gì (và làm thế nào) đang diễn ra:

root@sv01:~# echo -e "\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\\\ Hello!"
\\\ Hello!
root@sv01:~# echo -e "\n Hello!"

 Hello!
root@sv01:~# echo -e "\\n Hello!"

 Hello!
root@sv01:~# echo -e "\\\n Hello!"
\n Hello!

Tôi hoàn toàn bị mất ở đó, ví dụ, tại sao ba dấu gạch chéo ngược chỉ cung cấp một dấu gạch chéo ngược? Tôi mong đợi: hai cái đầu tiên sẽ được thoát thành một, cái thứ ba sẽ không tìm thấy gì để thoát nên nó sẽ vẫn là một dấu gạch chéo (dòng trong thí nghiệm đầu tiên), nhưng điều đang xảy ra là cái thứ ba sẽ biến mất.
Tại sao tôi nhận được một dấu gạch chéo ngược từ bốn \\\\ Hello? Tôi hy vọng mỗi cặp sẽ đưa ra một dấu gạch chéo ngược -> hai dấu gạch chéo ngược.

Và tại sao tôi cần ba dấu gạch chéo ngược trong trường hợp cuối cùng để thoát \ n? Điều gì đang xảy ra trong nền của việc trốn thoát để có được điều đó? và nó khác với \\ntrường hợp như thế nào?

Tôi đánh giá cao bất kỳ lời giải thích về những gì đang xảy ra trong các dòng trước.


echo -ehành vi không được xác định theo tiêu chuẩn nào - xem pubs.opengroup.org/onlinepub/9699919799/utilities/echo.html . Đầu ra hoàn toàn được xác định theo triển khai nếu có dấu gạch chéo theo nghĩa đen ở bất kỳ vị trí nào trong các đầu vào và tùy chọn được phép duy nhất là -n(có nghĩa là việc triển khai tuân thủ tiêu chuẩn sẽ được echo -ein -etrên đầu ra của nó).
Charles Duffy

... ngay cả khi bạn chắc chắn 100% rằng vỏ của bạn bị hỏng, thậm chí sau đó echo -e không an toàn: echosẽ hoạt động theo tiêu chuẩn nếu cả hai posixxpg_echotùy chọn thời gian chạy được bật hoặc nếu được biên dịch với các tùy chọn thời gian xây dựng tương đương. Cách thực hành an toàn là sử dụng printfthay thế - xem phần SỬ DỤNG ỨNG DỤNG và QUYẾT ĐỊNH của liên kết ở trên mô tả cách thực hiện printfhành động thay thế echo.
Charles Duffy

Câu trả lời:


28

Điều này là do bashecho -ekết hợp. Từman 1 bash

Dấu gạch chéo ngược không trích dẫn ( \) là ký tự thoát. Nó bảo tồn giá trị theo nghĩa đen của ký tự tiếp theo, ngoại trừ <newline>. [Càng]

Kèm theo ký tự trong dấu ngoặc kép giữ gìn giá trị văn chương của tất cả các ký tự trong dấu ngoặc kép, với ngoại lệ của $, `, \, [...] Các dấu chéo ngược vẫn giữ được ý nghĩa đặc biệt của nó chỉ khi theo sau là một trong những nhân vật sau: $,`, ", \, hoặc <newline>.

Vấn đề là: dấu gạch chéo kép được trích dẫn không phải lúc nào cũng đặc biệt.

Có nhiều cách thực hiện khác nhau echo, nói chung, đó là một nội dung bash; điều quan trọng ở đây là hành vi này:

Nếu -ecó hiệu lực, các trình tự sau đây được công nhận:
\\
xuyệc ngược
[...]
\n
dòng mới

Bây giờ chúng ta có thể giải mã:

  1. echo -e "\ Hello!"- không có gì đặc biệt bash, không có gì đặc biệt echo; \ở lại
  2. echo -e "\\ Hello!"- người đầu tiên \nói bashđể đối xử với người thứ hai theo \nghĩa đen; echođược \ Hello!và hành động như trên.
  3. echo -e "\\\ Hello!"- người đầu tiên \nói bashđể đối xử với người thứ hai theo \nghĩa đen; echođược \\ Hello!và (vì -e) nó nhận ra \\\.
  4. echo -e "\\\\ Hello!"- người đầu tiên \nói bashđể đối xử với người thứ hai theo \nghĩa đen; người thứ ba nói tương tự về người thứ tư; echođược \\ Hello!và (vì -e) nó nhận ra \\\.
  5. echo -e "\\\\\ Hello!"- người đầu tiên \nói bashđể đối xử với người thứ hai theo \nghĩa đen; người thứ ba nói tương tự về người thứ tư; cái cuối cùng không đặc biệt; echođược \\\ Hello!và (vì -e) nó nhận ra ban đầu \\\, cái cuối cùng \vẫn còn nguyên.

Và như thế. Như bạn có thể thấy, có tới bốn dấu gạch chéo ngược liên tiếp cho kết quả là một. Đó là lý do tại sao bạn cần (ít nhất) chín trong số họ để có được ba. 9 = 4 + 4 + 1.

Bây giờ với \n:

  1. echo -e "\n Hello!"- không có gì đặc biệt bash, echo có cùng chuỗi và (vì -e) nó diễn giải \nthành một dòng mới.
  2. echo -e "\\n Hello!"- bashdiễn giải \\như \; echođược \n Hello!và kết quả là giống như trên.
  3. echo -e "\\\n Hello!"- bashdiễn giải ban đầu \\\; echođược \\n Hello!và (vì -e) nó diễn giải \\như một nghĩa đen \cần được in.

Kết quả sẽ khác với 'thay vì "(do bashhành vi khác nhau ) hoặc không có -e( echohành vi khác nhau ).


1
Cảm ơn rât nhiều! Vì vậy, có hai bước thoát, bước được thực hiện bằng bash và bước thứ hai do -ethẩm phán văn bản đã được đánh giá bởi bash, điều đó có đúng không? nếu đó là chính xác, điều đó loại bỏ sự nhầm lẫn. Bạn có thể đề cập đến cách sedcư xử? Liệu nó có xây dựng riêng trong kỹ thuật thoát hiểm? vậy ý ​​tôi là nó có hoạt động như tiếng vang -ekhông?
Mohammed Noureldin

2
@MohammedNoureldin Vâng, có hai bước. Câu hỏi ban đầu của bạn là tốt, vì vậy, đừng làm cho nó quá phức tạp sed. Bạn có thể hỏi một câu hỏi khác mặc dù ( sedchỉ về ), chỉ cần làm nghiên cứu của riêng bạn đầu tiên.
Kamil Maciorowski

3
@MohammedNoureldin sedsẽ tuân theo các nguyên tắc cơ bản tương tự: bash sẽ diễn giải dòng lệnh theo quy tắc của nó, phân tích cú pháp (và có thể loại bỏ) dấu ngoặc kép và thoát. Kết quả của điều đó được chuyển đến sed, giải thích nó theo các quy tắc thoát của nó . BTW, bạn có thể đơn giản hóa điều này bằng cách sử dụng một chuỗi trích dẫn đơn bash, vì điều đó không có giải thích thoát eny (bằng bash) - bash xóa các dấu ngoặc đơn và chuyển trực tiếp những gì bên trong chúng vào lệnh.
Gordon Davisson

Tôi vẫn có một vấn đề nhỏ trong echo -e "\\\n Hello!"trường hợp. Ở đây bash sẽ thoát, và nó sẽ trở thành \\n, sau đó -esẽ thoát khỏi hai dấu gạch chéo ngược \\nvà sau đó chúng sẽ trở thành \n. Bây giờ ai giải thích \nđể làm cho nó dòng mới? Thông thường trong trường hợp echo -e "\n Hello!", bash không làm gì và -ediễn giải \nthành dòng mới. nhưng trong quá trình giải thích tình huống được đề cập đầu tiên đã được thực hiện trước khi \nđược giải thích. Bạn có thể giải thích điều đó không?
Mohammed Noureldin

1
Được rồi, lỗi của tôi, tôi đã đọc về điều đó trong 2 ngày với các đêm của họ, vì vậy rõ ràng tôi đã bắt đầu trộn lẫn các vụ án, tôi tin rằng tôi đã có một điều gì sedđó khiến tôi bối rối tối qua (có thể tôi đã làm gì đó sai ngày hôm qua), nhưng bây giờ tôi đã thử lại tương tự với echo -esed, và tôi đã nhận được điều tương tự như ngoại trừ, cảm ơn!
Mohammed Noureldin
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.