Tại sao tiếng vang thanh bar-âm thanh -n khác với tiếng vang -n âm thanh thanh?


10

Đối chiếu

echo -n "bar"

với

echo "bar" -n

Cái trước làm những gì tôi nghĩ nó phải làm (in "thanh" mà không có dòng mới), trong khi cái trước thì không. Đây là một lỗi hoặc do thiết kế? Tại sao nó khác với nhiều chương trình cli ở chỗ bạn không thể di chuyển các tùy chọn xung quanh? Ví dụ, tail -f /var/log/messageshoàn toàn giống như tail /var/log/messages -f. Đôi khi tôi làm cái sau khi tôi quên tôi muốn cái trước, bởi vì bên trong các tùy chọn và đối số được sắp xếp lại, thường là bằng getopt .

Cập nhật: có tôi ban đầu nerf-ed câu hỏi của tôi. Tôi đã xóa nerf bạn sẽ phải xem lịch sử để làm cho một số câu trả lời có ý nghĩa.


3
Từ những gì tôi thấy, sự khác biệt rõ ràng ngay lập tức. echo -n "bar"đưa ra "thanh", trong khi echo "bar" -ncho "thanh -n"
phunehehe

Câu trả lời:


18

Như hầu hết những người khác đã quan sát, "-n" được hiểu theo nghĩa đen nếu được đặt ở bất cứ đâu nhưng ngay sau echolệnh.

Trong lịch sử, các tiện ích UNIX đều như thế này - chúng chỉ tìm kiếm các tùy chọn ngay sau tên lệnh. Có khả năng BSD hoặc GNU đã tiên phong cho phong cách linh hoạt hơn (mặc dù tôi có thể sai), vì ngay cả bây giờ POSIX chỉ định cách cũ là chính xác (xem Hướng dẫn 9 và cả man 3 getopttrên hệ thống Linux). Dù sao, mặc dù hầu hết các tiện ích Linux ngày nay đều sử dụng kiểu mới, vẫn có một số phần như thế echo.

Echolà một mớ hỗn độn, tiêu chuẩn khôn ngoan, trong đó có ít nhất hai phiên bản xung đột cơ bản được chơi vào thời điểm POSIX ra đời. Một mặt, bạn có kiểu SYSV, phiên dịch các ký tự thoát dấu gạch chéo ngược nhưng xử lý các đối số của nó theo nghĩa đen, không chấp nhận các tùy chọn. Mặt khác, bạn có kiểu BSD, xử lý một chữ cái đầu -nnhư một trường hợp đặc biệt và xuất ra hoàn toàn mọi thứ khác theo nghĩa đen. Và vì echorất tiện lợi, bạn có hàng ngàn tập lệnh shell phụ thuộc vào hành vi này hay hành vi khác:

echo Usage: my_awesome_script '[-a]' '[-b]' '[-c]' '[-n]'
echo -a does a thing.
echo -b does something else.
echo -c makes sure -a works right.
echo -- DON\'T USE -n -- it\'s not finished! --

Do ngữ nghĩa "đối xử với mọi thứ theo nghĩa đen", thậm chí không thể thêm tùy chọn mới echomà không phá vỡ mọi thứ. Nếu GNU sử dụng sơ đồ tùy chọn linh hoạt trên nó, địa ngục sẽ vỡ ra.

Ngẫu nhiên, để tương thích tốt nhất giữa các triển khai shell Bourne, hãy sử dụng printfchứ không phảiecho .

CẬP NHẬT để giải thích tại sao echođặc biệt không sử dụng các tùy chọn linh hoạt.


upvote vì bạn là người duy nhất đề cập đến đó là hành vi getopt dự kiến.
Geoffrey Bachelet

@jander tại sao tiếng vang lại là "tiếng kêu"? Tôi nghĩ rằng đó là một coreutil gnu?
xenoterracide

@xeno: Tôi đã cập nhật câu trả lời của mình. Về cơ bản, GNU không muốn phá vỡ mọi thứ.
Jander

1
Tùy chọn chấp nhận sau khi phi tùy chọn đầu tiên là cụ thể cho GNU tiện ích và chương trình sử dụng GNU libc 's getopt cơ sở vật chất. Người dùng luôn có thể có hành vi tương thích ngược bằng cách đặt biến môi trường POSIXLY_CORRECT.
Gilles 'SO- ngừng trở nên xấu xa'

1
Đối với trường hợp cụ thể echo, cũng có các triển khai nhận ra -ehoặc -Elà tùy chọn. Đối với tính di động, không bắt đầu với -hoặc sử dụng một cái gì đó như printf %s -e.
Gilles 'SO- ngừng trở nên xấu xa'

9

Các câu trả lời khác đến điểm mà bạn có thể nhìn vào trang man để thấy rằng -n đang trở thành một phần của chuỗi để lặp lại. Tuy nhiên tôi chỉ muốn chỉ ra rằng thật dễ dàng để điều tra điều này mà không cần md5sum và làm cho những gì đang diễn ra ít khó hiểu hơn.

[11:07:44][dasonk@Chloe:~]: echo -n "bar"
bar[11:07:48][dasonk@Chloe:~]: echo "bar" -n
bar -n

3
+1 chính xác. Nếu một đường ống không làm những gì bạn mong đợi, hãy kiểm tra từng phần riêng biệt.
Mikel

6

Wow, lời giải thích của mọi người là dài.

Thật đơn giản:

-n là một tùy chọn nếu nó xuất hiện trước chuỗi, nếu không, nó chỉ là một chuỗi khác được lặp lại.

Xóa | md5sum và bạn sẽ thấy đầu ra là khác nhau.


5

Từ kiểm tra đơn giản, đây không phải là lỗi do thiết kế ...

echo "bar" -n | md5sum

a3f8efa5dd10e90aee0963052e3650a1

Hãy thử lệnh này cho chính mình:

echo "bar -n" | md5sum

Bạn sẽ nhận thấy rằng md5 kết quả là

a3f8efa5dd10e90aee0963052e3650a1

Bạn chỉ cần trộn lẫn việc sử dụng -n trong echo.

Trong mã mẫu đầu tiên của bạn

echo -n "bar" | md5sum

-n được sử dụng để nói KHÔNG đặt một dòng mới sau tiếng vang này.

Mẫu thứ hai của bạn

echo "bar" -n | md5sum

đang coi -n như một văn bản nghĩa đen.

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.