อะไรคือความแตกต่างระหว่าง $ (สิ่งของ) และ `สิ่งของ '?


265

มีสองไวยากรณ์สำหรับการทดแทนคำสั่ง: ด้วยดอลลาร์วงเล็บและ backticks วิ่งtop -p $(pidof init)และtop -p `pidof init`ให้ผลลัพธ์เดียวกัน มีสองวิธีในการทำสิ่งเดียวกันหรือมีความแตกต่าง?


18
ดูเพิ่มเติม: BashFAQ / 082
Dennis Williamson

42
สำหรับวินาทีนั้นฉันคิดว่านี่เป็นคำถาม jQuery
David Murdoch

ผลลัพธ์อาจขึ้นอยู่กับเชลล์ - บางตัวรองรับทั้งคู่
artdanil

คำตอบ:


359

backquotes แบบเก่า` `ทำ backslashes และซ้อนกันเล็กน้อย รูปแบบใหม่$()ตีความทุกอย่างในระหว่าง( )เป็นคำสั่ง

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

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

ใช้งานได้หาก backquotes ซ้อนอยู่หลบหนี:

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

แบ็กสแลชสนุก:

echo $(echo '\\')
\\

echo `echo '\\'`
\

รูปแบบใหม่$()ใช้กับเชลล์ที่สอดคล้องกับPOSIXทั้งหมด
ในฐานะที่เป็นmouvicielชี้ให้เห็นแบบเก่า` `อาจจะจำเป็นสำหรับเปลือกหอยเก่า

นอกเหนือจากมุมมองทางเทคนิคแบบเก่า` `ยังมีข้อเสียทางสายตา:

  • สังเกตยาก: I like $(program) better than `program`
  • สับสนได้อย่างง่ายดายด้วยคำพูดเดียว: '`'`''`''`'`''`'
  • พิมพ์ไม่ง่าย (อาจไม่ได้อยู่ในเค้าโครงมาตรฐานของแป้นพิมพ์)

(และ SE ใช้` `เพื่อจุดประสงค์ของตัวเองมันเป็นความเจ็บปวดที่เขียนคำตอบนี้ :)


10
สิ่งเดียวที่ฉันจะเพิ่มคือฉันเรียก '(' paren ไม่ใช่วงเล็บ (ซึ่งคือ '[').
Kendall Helmstetter Gelner

@Kendall: และที่นี่ฉันคิดว่า '{' เป็นวงเล็บซ้ายสำหรับทุกปีที่ผ่านมา ...
SAMB

5
@Sam: { }มักจะเรียกว่า "วงเล็บปีกกา" หรือ "วงเล็บ" en.wikipedia.org/wiki/Braces_(punctuation)#Braces
Jørn Schou-Rode

2
ฉันหมายถึง '{' เป็นเครื่องหมายปีกกา แม้ว่ามันจะดูแปลกที่คุณต้องเพิ่ม qualifier "หยิก" ถ้าคุณเรียกสิ่งอื่น ๆ วงเล็บ ... ฉันเดาว่ามันเป็นเพียงเพราะพวกเขาจริงขด
Kendall Helmstetter Gelner

1
@slim ฉันไม่รู้บน US / UK keyboards แต่บน spanish keyboards `เป็นคีย์ที่ตายแล้วดังนั้นฉันต้องพิมพ์ backtick สองครั้ง (สิ่งที่ฉันมักจะลืมว่าฉันทำได้) หรือ backtick space ซึ่งเป็น ความเจ็บปวด
Darkhogg

41

แตกต่างที่ชัดเจนผมสังเกตคือการที่คุณไม่สามารถ backticks $()รังขณะที่คุณสามารถทำรัง อาจมีอยู่ทั้งคู่ด้วยเหตุผลดั้งเดิม ในทำนองเดียวกันคำสั่ง.และsourceมีความหมายเหมือนกัน


10
sourceบางหอยบอร์นที่ได้มาไม่รู้จัก ขีดกลางเป็นตัวอย่างหนึ่ง
Dennis Williamson

14
ที่ไม่เป็นความจริง. คุณสามารถซ้อน backtick ไปที่ระดับใดก็ได้ยิ่งเจ็บปวดมากขึ้น โปรดทราบว่าทั้งสอง$(...)และ`...`เป็นมาตรฐาน (หลังถูกคัดค้าน) ในขณะที่.เป็นมาตรฐาน แต่ไม่ใช่source
Stéphane Chazelas

3
การแก้ไข(t)cshจะไม่สามารถซ้อนในได้ (t)cshไม่สนับสนุน$(...)แม้ว่า พวกเขาให้การสนับสนุนsource(ไม่ใช่.)
Stéphane Chazelas

28

$()ไม่ทำงานกับเชลล์เป้าหมายเก่า แต่เป็นเวลาหลายสิบปีมาแล้วที่ฉันทำงานกับ Bourne shell เก่า


เก่าเท่าในปี 1970 และต้นปี 1980 ถูกต้องไหม
Christopher

6

หมายเหตุอื่น$()จะใช้ทรัพยากรระบบมากกว่าการใช้ backticks แต่เร็วขึ้นเล็กน้อย

ในMastering Unix shell scripting , Randal K. Michael ได้ทำการทดสอบในบทที่ชื่อว่า "24 Ways to Process File Line-by-Line"


2
การอ้างสิทธิ์นี้ไร้สาระ ไม่มีเหตุผลว่าทำไมมันควรจะเร็วกว่าเพราะมันเป็นเพียงการใช้สัญลักษณ์ที่แตกต่างกันสำหรับ parser
schily

@ schily: บางทีฉันแค่อ้างจากหนังสือคุณสามารถอ่านได้สำหรับรายละเอียดเพิ่มเติม
cuonglm

3
ฉันมักจะเห็นด้วยกับ @schily ... ทำไมต้องใช้ทรัพยากรมากขึ้น?
Wildcard

2
@ Wildcard ฉันคิดว่าเป็นเพราะ$()ทำให้สคริปต์ของคุณมีขนาดใหญ่กว่าหนึ่งไบต์ถ้าใช้`(สมมติว่าคุณไม่ซ้อนกันและไม่ใช้แบ็กสแลชภายใน) ซึ่งจะเร็วกว่าในการแยกที่จะแตกต่างกันระหว่างเปลือกหอยและจะไม่เกี่ยวข้องเล็กน้อยเมื่อเทียบกับค่าใช้จ่ายในการสร้างท่อและการฟอร์กของกระบวนการซึ่งการทดแทนคำสั่งเกี่ยวข้อง
Stéphane Chazelas

5

หากต้องการเพิ่มสิ่งที่ผู้อื่นพูดที่นี่คุณสามารถใช้ backticks เพื่อจำลองความคิดเห็นแบบอินไลน์:

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

ผลลัพธ์คือ: foo bar.

ดูข้อมูลเพิ่มเติมได้ที่: https://stackoverflow.com/a/12797512 (โปรดสังเกตความคิดเห็นด้านล่างที่โพสต์นั้น)


1

$()ไวยากรณ์จะไม่ทำงานกับบอร์นเชลล์เก่า
ด้วยเชลล์ที่ใหม่กว่า` `และ$()เทียบเท่า แต่$()สะดวกกว่าเมื่อคุณต้องการซ้อนหลายคำสั่ง

ตัวอย่างเช่น

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

ง่ายกว่าในการพิมพ์และตรวจแก้จุดบกพร่องกว่า:

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

1
ในขณะที่ $ () อาจดูดี แต่เป็นความเจ็บปวดเมื่อใช้ตัวแยกวิเคราะห์ที่เกี่ยวข้องเนื่องจากต้องใช้ตัวแยกวิเคราะห์แบบเรียกซ้ำ
schily

6
@ schily ในอีกด้านหนึ่งสิ่งที่จะเป็นเปลือกโดยไม่มีการแยกวิเคราะห์ที่ดี
Emmanuel

1
ปัญหาคือคุณต้องทราบว่าสตริงสิ้นสุดลงก่อนที่คุณจะเรียก parser มันค่อนข้างง่ายสำหรับ backticks แต่มันยากกับวงเล็บเพราะมันถูกใช้เพื่อวัตถุประสงค์ต่าง ๆ ในเปลือก ดังนั้นคุณต้องใช้เครื่องมือแยกวิเคราะห์สองครั้งและในลักษณะที่ไม่มีอยู่ใน Bourne Shell
schily
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.