Sự khác biệt giữa $ (thứ) và `Stuff` là gì?


265

Có hai cú pháp để thay thế lệnh: với dấu ngoặc đơn và với backticks. Chạy top -p $(pidof init)top -p `pidof init`cho cùng một đầu ra. Có phải hai cách làm cùng một điều, hoặc có sự khác biệt?



42
Trong một giây, tôi nghĩ đây là một câu hỏi về jQuery.
David Murdoch

Kết quả có thể phụ thuộc vào vỏ - một số hỗ trợ cả hai.
artdanil

Câu trả lời:


359

Các backquote kiểu cũ ` `xử lý dấu gạch chéo ngược và lồng một chút khác nhau. Kiểu mới $()diễn giải mọi thứ ở giữa ( )như một lệnh.

echo $(uname | $(echo cat))
Linux

echo `uname | `echo cat``
bash: command substitution: line 2: syntax error: unexpected end of file
echo cat

hoạt động nếu các backquote lồng nhau được thoát:

echo `uname | \`echo cat\``
Linux

dấu gạch chéo vui:

echo $(echo '\\')
\\

echo `echo '\\'`
\

Kiểu mới $()áp dụng cho tất cả các vỏ phù hợp POSIX .
Như mouviciel đã chỉ ra, kiểu cũ ` `có thể cần thiết cho đạn pháo cũ.

Ngoài quan điểm kỹ thuật, kiểu cũ ` `cũng có nhược điểm về thị giác:

  • Khó để ý: I like $(program) better than `program`
  • Dễ bị nhầm lẫn với một trích dẫn duy nhất: '`'`''`''`'`''`'
  • Không dễ gõ như vậy (thậm chí có thể không phải trên bố cục tiêu chuẩn của bàn phím)

(và SE sử dụng ` `cho mục đích riêng, thật đau đớn khi viết câu trả lời này :)


10
Điều duy nhất tôi muốn nói thêm là tôi gọi '(' một paren, không phải là một dấu ngoặc (đó là '[').
Kendall Helmstetter Gelner

@Kendall: và ở đây tôi nghĩ '{' là khung bên trái cho tất cả những năm đó ...
SamB

5
@Sam: { }thường được gọi là "dấu ngoặc nhọn" hoặc "niềng răng" en.wikipedia.org/wiki/Braces_(punctuation)#Braces
Jørn SCHOU-Rode

2
Tôi cũng gọi '{' là dấu ngoặc nhọn. Mặc dù có vẻ kỳ lạ, bạn cần thêm vòng loại "xoăn" nếu bạn gọi các dấu ngoặc khác ... Tôi đoán đó chỉ là vì chúng thực sự cong.
Kendall Helmstetter Gelner

1
@slim Tôi không biết trên bàn phím US / UK, nhưng trên bàn phím tiếng Tây Ban Nha `là một phím chết, vì vậy tôi phải gõ một backtick đôi (một điều tôi thường quên tôi thậm chí có thể làm) hoặc backtick sau đó là dấu cách, đó là một đau đớn.
Darkhogg

41

Rõ ràng sự khác biệt tôi quan sát là bạn không thể lồng backticks trong khi bạn có thể lồng $(). Có lẽ cả hai tồn tại vì lý do di sản. Tương tự, các lệnh .sourcelà từ đồng nghĩa.


10
Một số vỏ có nguồn gốc từ Bourne không nhận ra source. Dash là một ví dụ.
Dennis Williamson

14
Đo không phải sự thật. Bạn có thể lồng backtick đến bất kỳ cấp độ nào, chỉ đau đớn hơn. Lưu ý rằng cả hai $(...)`...`đều là tiêu chuẩn (cái sau bị phản đối) trong khi .là tiêu chuẩn nhưng không phảisource
Stéphane Chazelas

3
Sửa chữa, chỉ trong (t)cshchúng không thể được lồng nhau. (t)cshkhông hỗ trợ $(...)mặc dù. Họ hỗ trợ source(và không .) mặc dù.
Stéphane Chazelas

28

$()không hoạt động với vỏ Bourne cũ. Nhưng đã nhiều năm trôi qua kể từ khi tôi làm việc với vỏ Bourne cũ.


Cũ như những năm 1970 và đầu những năm 1980, đúng không?
Christopher

6

Một lưu ý khác, $()sẽ sử dụng nhiều tài nguyên hệ thống hơn là sử dụng backticks, nhưng nhanh hơn một chút.

Trong việc làm chủ kịch bản shell Unix , Randal K. Michael đã thực hiện một thử nghiệm trong một chương có tên "24 cách để xử lý từng dòng một tệp".


2
Yêu cầu này là vô nghĩa. Không có lý do tại sao nó phải nhanh hơn vì nó chỉ sử dụng một ký hiệu khác cho trình phân tích cú pháp.
schily

@schily: Có thể, tôi chỉ trích dẫn từ cuốn sách, bạn có thể đọc nó để biết thêm chi tiết.
cuonglm

3
Tôi có xu hướng đồng ý với @schily ... tại sao nó lại cần nhiều tài nguyên hơn?
Wildcard

2
@Wildcard, tôi cho rằng đó là vì $()làm cho tập lệnh của bạn lớn hơn một byte so với khi nó được sử dụng `(giả sử bạn không lồng chúng và không sử dụng dấu gạch chéo ngược trong). Vì nó sẽ nhanh hơn để phân tích cú pháp, điều đó sẽ khác nhau giữa các đạn pháo và sẽ không liên quan vì không đáng kể so với chi phí tạo ra một đường ống và từ bỏ quá trình thay thế lệnh.
Stéphane Chazelas

5

Để thêm vào những gì người khác nói ở đây, bạn có thể sử dụng backticks để mô phỏng các bình luận nội tuyến:

echo foo `# I'm a comment!` bar

Đầu ra là : foo bar.

Xem phần sau để biết thêm thông tin: https://stackoverflow.com/a/12797512 (Lưu ý cả những bình luận bên dưới bài đăng đó.)


1

Các $()cú pháp sẽ không làm việc với vỏ bourne cũ.
Với các shell mới hơn ` `$()tương đương nhưng $()sử dụng thuận tiện hơn nhiều khi bạn cần lồng nhiều lệnh.

Ví dụ :

echo $(basename $(dirname $(dirname /var/adm/sw/save )))

dễ gõ và gỡ lỗi hơn:

echo `basename \`dirname \\\`dirname /var/adm/sw/save \\\`\``

1
Mặc dù $ () có thể trông đẹp mắt, nhưng thật khó khăn khi triển khai trình phân tích cú pháp có liên quan vì nó yêu cầu trình phân tích cú pháp đệ quy kép.
schily

6
@schily Mặt khác, cái gì sẽ là một cái vỏ nếu không có trình phân tích cú pháp tốt.
Emmanuel

1
Vấn đề là bạn cần biết chuỗi kết thúc ở đâu trước khi bạn gọi trình phân tích cú pháp. Điều này tương đối đơn giản với backticks, nhưng nó khó với dấu ngoặc vì chúng được sử dụng cho các mục đích khác nhau trong shell. Vì vậy, bạn cần trình phân tích cú pháp hai lần và theo cách không tồn tại trong Bourne Shell.
schily
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.