Tại sao các lệnh echo echo -e của dường như không tạo ra đầu ra đúng?


21

Trong thiết bị đầu cuối của Ubuntu 18.04 LTS, khi tôi viết lệnh này:

echo -e "Hello\\\n"

Nó cung cấp điều này như là đầu ra:

Hello\n

Nhưng nó nên in, như trang người đàn ông nói:

Hello\

Đó là, in đầu tiên Hello, sau đó \, sau đó là một ký tự dòng mới (và sau đó là một dòng mới khác). Vấn đề ở đâu?

Xem một vài echo -elệnh và đầu ra của chúng :

man420@man420-X542UQ:~$ echo -e "HEllo\a\a\a\a\a\a\\\n"
HEllo\n
man420@man420-X542UQ:~$ echo -e "HEllo\\\n"
HEllo\n
man420@man420-X542UQ:~$ echo -e "HEllo\a\\\n"
HEllo\n

yes.for đầu tiên 2 \ nó nên ra một \ .và cuối cùng \ n và tạo ra một lối thoát xuyệc ngược \ n (dòng mới) .so do tại sao nó nên in Xin chào \
yolin00

1
Hãy thử nó mà không có dấu ngoặc kép.
ajgringo619

2
Một câu trả lời tuyệt vời đã được cung cấp bởi Eliah Kagan, mà bạn nên chấp nhận.
vanadi

2
Đừng sử dụng echoở nơi đầu tiên: sử dụng printf.
chepner

2
Luôn sử dụng các trích dẫn đơn nếu bạn muốn chắc chắn rằng những gì bạn viết chính xác là những gì được truyền cho lệnh dưới dạng đối số.
Giacomo Alzetta

Câu trả lời:


29

Dấu gạch chéo ngược được xử lý đặc biệt bằng cách echo -e, nhưng trước tiên, đôi khi chúng được xử lý đặc biệt bằng vỏ (trong trường hợp này là bash), theo quy tắc trích dẫn của vỏ .

Đối số echothực sự nhìn thấy là Hello\\n. Bởi vì bạn đã trôi qua -eđến echo, nó xử lý thoát xuyệc ngược đặc biệt, và \\được thu nhỏ đến một single \. Trận chung kết nkhông được thoát, vì vậy nó xuất hiện theo nghĩa đen.

Lý do cho điều này là, trước và tách biệt với hoạt động của echochính nó, vỏ xử lý \đặc biệt trong một số bối cảnh nhưng không phải là khác. Các \ký tự không được trích dẫn luôn được xử lý đặc biệt, trích dẫn\ đơn không bao giờ được xử lý đặc biệt, nhưng việc xử lý các ký tự được trích dẫn kép \ , như trong lệnh bạn đã chạy, tinh tế và phức tạp hơn.

Khi shell gặp văn bản trích dẫn kép trong một lệnh, như với "Hello\\\n", nó xử lý \như một ký tự thoát khi nó đứng trước một ký tự có thể có ý nghĩa đặc biệt bên trong dấu ngoặc kép chứ không phải khác .

  1. Bởi vì \đôi khi có một ý nghĩa đặc biệt bên trong "", một \cái ngay trước một cái khác \có tác dụng trích dẫn thứ hai đó \. Vì vậy, bên trong dấu ngoặc kép, đầu tiên \\được thu gọn vào \.
  2. Sau hai \ký tự đầu tiên đó, có một \ký tự thứ ba không bị ảnh hưởng bởi hai ký tự đầu tiên và trước một ký tự n. Nhưng nkhông phải là một nhân vật được đối xử đặc biệt trong dấu ngoặc kép, vì vậy \trước đó nó không được đối xử đặc biệt trong tình huống này. Do đó \nở lại \n.

Hiệu quả là, trong dấu ngoặc kép, \\\nđược hiểu là \\n.

Khi echo -enhìn thấy \\n, cái đầu tiên \loại bỏ ý nghĩa đặc biệt từ cái thứ hai, vì vậy hãy echoin theo \nnghĩa đen cho văn bản đó.


Nếu mục tiêu của bạn là in Hellothêm một dòng mới nhưng không có dấu gạch chéo ngược (câu hỏi ban đầu không rõ ràng về điều này, cộng với tôi nghĩ đó là một ví dụ hữu ích), thì một giải pháp là loại bỏ a \. Chạy echo -e "Hello\\n"đầu ra Hellovới một dòng mới bổ sung vào cuối.

Một giải pháp tốt hơn là sử dụng dấu ngoặc đơn và viết echo -e 'Hello\n'. Trích dẫn duy nhất là hình thức mạnh nhất của trích dẫn. Một giải pháp thậm chí tốt hơn thường là sử dụng printfthay vì echo, trong trường hợp này sẽ là printf 'Hello\n\n'.

Nếu mục tiêu của bạn là in Hello\bao gồm dấu gạch chéo ngược, theo sau là một dòng mới , thì cách tiếp cận được trích dẫn kép là có thể nhưng rườm rà. Để tìm ra nó, hãy làm việc ngược lại: echo -echuyển đổi \\sang \\nthành một dòng mới, và trích dẫn hai lần chuyển đổi \\thành \, do đó bạn có thể thực hiện với sáu dấu gạch chéo ngược ( echo -e "Hello\\\\\\n"), vì \\nbiến thành \nmột dấu gạch chéo ngược thoát khỏi dấu gạch chéo khác. Bạn cũng có thể làm điều đó với năm, vì trích dẫn kép giữ lại \nkhi \không thoát.

Điều này minh họa lợi ích của trích dẫn đơn: chỉ cần đặt bất cứ điều gì bạn muốn echo -ethấy bên trong dấu ngoặc đơn ( echo -e 'Hello\\\n'). printfở đây cũng tốt Một lựa chọn là printf 'Hello\\\n\n'. Nhưng nơi printfthực sự tỏa sáng là bạn có thể cắm thêm các đối số. Bạn có thể sử dụng printf '%s\n\n' 'Hello\', trong đó chèn đối số thứ hai (theo nghĩa đen Hello\bởi vì các trích dẫn đơn lẻ không thay đổi bất cứ điều gì) thay cho %s.

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.