อะไรคือข้อแตกต่างระหว่าง $ (command) และ `command` ในการเขียนโปรแกรมเชลล์?


258

ในการจัดเก็บเอาต์พุตของคำสั่งเป็นตัวแปรใน sh / ksh / bash คุณสามารถทำได้

var=$(command)

หรือ

var=`command`

ความแตกต่างระหว่างสองวิธีคืออะไร?



คุณจะพบกับปัญหาที่ซ้อนกันรายละเอียดใน Git Coding แนวทาง: เห็นคำตอบของฉันด้านล่าง
VonC

ที่เกี่ยวข้อง: unix.stackexchange.com/questions/126927
Kusalananda

คำตอบ:


274

backticks / gravemarks ได้รับการคัดค้านในความโปรดปรานของ$()เพื่อทดแทนคำสั่งเพราะสามารถซ้อนได้อย่างง่ายดายภายในตัวเองในขณะที่$() $(echo foo$(echo bar))มีความแตกต่างอื่น ๆ เช่นวิธีวิเคราะห์เครื่องหมายแบ็กสแลชในเวอร์ชัน backtick / gravemark เป็นต้น

ดูBashFAQ / 082ด้วยเหตุผลหลายประการเพื่อชอบไวยากรณ์ $ (... ) เสมอ

ดูข้อมูลจำเพาะPOSIXสำหรับข้อมูลโดยละเอียดเกี่ยวกับความแตกต่างหลากหลาย


25
ลิงก์ที่ดี แต่ข้อความนั้นไม่สนับสนุน backquotes ที่เหมาะสม$(...)- เพียงบันทึกเป็นทางเลือก
Norman Grey

24
@NormanGray POSIX อาจไม่พูดคำว่าเลิกใช้แต่บอกว่า"the backquoted variety of command substitution is not recommended"เป็นวิธีที่ยืดยาวในการพูดที่เลิกใช้ IMHO
SiegeX

11
POSIX ไม่ได้คัดค้าน backticks แต่ถูกเพิ่ม$(...)เป็นวิธีทางเลือก มีเป็นที่รู้จักกันไม่มีข้อผิดพลาดการดำเนินการกับ backticks $(...) แต่มีหลายข้อบกพร่องการดำเนินงานที่เป็นที่รู้จักด้วย ดังนั้นสำหรับปัญหาเรื่องการพกพาแนะนำให้ใช้ backticks สำหรับการโทรที่ไม่ซ้อนกัน $(...)ต้องการตัวแยกวิเคราะห์แบบเรียกซ้ำ แต่ไม่ได้ใช้กับ ksh86 ที่แนะนำคุณลักษณะนี้ ตรวจสอบin-ulm.de/~mascheck/various/cmd-subst สำหรับรายการการปรับใช้ที่ถูกต้อง เชลล์ที่สอดคล้องกันจำเป็นต้องรองรับเคสทั้งหมดยกเว้นเคส D.2
schily

2
มีสิ่งอื่น ๆ ใน POSIX ที่ต้องถูกมองว่าเป็นdeprecatedเช่นการใช้waitpid()ที่ป้องกันไม่ให้คุณเห็นเต็ม 32 บิตจากexit()พารามิเตอร์ แต่เชลล์ทั้งหมดยกเว้นเชลล์ Bourne ล่าสุดยังคงใช้waitpid()แทนการwaitid()โทรที่มีให้ตั้งแต่ตอนนี้ 26 ปี
Schily

การเชื่อมโยงในคำแนะนำที่เป็นคำตอบที่มีความแตกต่างบางอย่างระหว่าง backticks และ$()ซึ่งจะมีการอธิบายเพิ่มเติมในส่วนของเอกสารนี้ ความแตกต่างไม่เพียง แต่เกี่ยวกับการทำรัง
โปรแกรมเมอร์บางคนเพื่อน

39

พวกเขาประพฤติตนเหมือนกัน ความแตกต่างคือการสร้างประโยค: ง่ายกว่าการทำรัง$()มากกว่า``:

listing=$(ls -l $(cat filenames.txt))

เมื่อเทียบกับ

listing=`ls -l \`cat filenames.txt\``

10
echo $(echo \$abc)ไม่เหมือนกับecho `echo \$abc`‍- ความแตกต่างยังมีอยู่$(echo \`)และ $(echo \\)
Peter.O

แตกต่างก็คือ: VSecho foo `#comment` echo foo $(#comment)อันที่สองไม่ทำงาน (ใช้สำหรับการแสดงความคิดเห็นในคำสั่งหลายบรรทัด)
wisbucky

27

กรกฎาคม 2014: คอมมิท f25f5e6 (โดยElia Pinto ( devzero2000) , เมษายน 2014, Git 2.0) เพิ่มปัญหาการซ้อน:

รูปแบบ backquote เป็นวิธีดั้งเดิมสำหรับการทดแทนคำสั่งและรองรับโดย POSIX
อย่างไรก็ตามการใช้ที่ง่ายที่สุดทั้งหมดนั้นซับซ้อนอย่างรวดเร็ว
โดยเฉพาะอย่างยิ่งการแทนคำสั่งที่ฝังตัวและ /
หรือการใช้คำพูดคู่ต้องหนีระมัดระวังด้วยตัวอักษรทับขวา

นั่นคือเหตุผลที่git / เอกสาร / CodingGuidelinesกล่าวถึง:

เราต้องการ$( ... )แทนที่คำสั่ง; ซึ่งแตกต่างจาก `` มันถูกต้องรัง
มันน่าจะเป็นวิธีที่ Bourne สะกดมันตั้งแต่วันแรก แต่น่าเสียดายที่ไม่ใช่

thiton แสดงความคิดเห็น :

นั่นคือเหตุผลที่`echo `foo`` จะไม่ทำงานโดยทั่วไปเนื่องจากความกำกวมโดยธรรมชาติเพราะแต่ละคน``สามารถเปิดหรือปิด
มันอาจใช้ได้กับกรณีพิเศษเนื่องจากโชคหรือคุณสมบัติพิเศษ


อัปเดตมกราคม 2559: Git 2.8 (มีนาคม 2559) กำจัดการตีกลับทั้งหมด

ดูกระทำ ec1b763 , กระทำ 9c10377 , กระทำ c7b793a , กระทำ 80a6b3f , กระทำ 9375dcf , กระทำ e74ef60 , กระทำ 27fe43e , กระทำ 2525c51 , กระทำ becd67f , กระทำ a5c98ac , กระทำ 8c311f9 , กระทำ 57da049 , กระทำ 1d9e86f , กระทำ 78ba28d , กระทำ efa639f , กระทำ 1be2fa0 , กระทำ 38e9476 , กระทำ 8823d2f , กระทำ 32858a0 , กระทำ cd914d8(12 มกราคม 2016) โดยเอเลียปินโต (devzero2000 )
(ผสานโดยJunio ​​C Hamano - gitster- in e572fef , 22 Jan 2016)

จาก Git 2.8 เป็นต้นไปมันคือทั้งหมดที่$(...)ไม่มีอีก`...`แล้ว


2
$()ยังระบุด้วย POSIX - คำพูดที่อธิบาย backticks ว่า "รองรับ POSIX" ในลักษณะที่บ่งบอกว่านี่เป็นลักษณะเฉพาะของพวกเขาที่ทำให้เข้าใจผิด เป็นยุคก่อน POSIX Bourne เท่านั้น (1970s) ที่ backticks เป็นไวยากรณ์ที่สนับสนุนเท่านั้น
ชาร์ลส์ดัฟฟี่

25

เมื่อใช้แบบฟอร์มย้อนหลังขีดเก่าเครื่องหมายทับขวาจะคงความหมายตามตัวอักษรยกเว้นเมื่อตามด้วย $, `หรือ \ back-tick แรกที่ไม่นำหน้าด้วย backslash จะยุติการทดแทนคำสั่ง

เมื่อใช้$(command)รูปแบบที่ใหม่กว่าอักขระทั้งหมดระหว่างวงเล็บจะประกอบขึ้นเป็นคำสั่ง ไม่มีใครได้รับการดูแลเป็นพิเศษ

ทั้งสองรูปแบบสามารถซ้อนกันได้ แต่ความหลากหลายของแบ็คขีดต้องใช้แบบฟอร์มต่อไปนี้

`echo \`foo\`` 

ตรงข้ามกับ:

$(echo $(foo))

1
การแก้ไขเล็กน้อยทั้งเวอร์ชันแบ็คทิคและ$()เวอร์ชันสอดคล้องกับ POSIX
SiegeX

5

มีความแตกต่างเล็กน้อยยกเว้นอักขระที่ไม่ใช้ค่า Escape ที่คุณสามารถใช้ภายในคำสั่ง คุณสามารถใส่คำสั่ง`... 'ในคำสั่ง$ (... ) (และในทางกลับกัน) สำหรับการทดแทนคำสั่งสองระดับลึกที่ซับซ้อนมากขึ้น

มีการตีความอักขระเครื่องหมายทับขวา / โอเปอเรเตอร์ที่แตกต่างกันเล็กน้อย เหนือสิ่งอื่นใดเมื่อวางคำสั่งการแทนที่"... "คุณต้องหลีกเลี่ยงอักขระ`ภายในที่มี\ในขณะที่มี$ substition ($)จะเข้าใจการทำรังโดยอัตโนมัติ


0

"อะไรคือความแตกต่างระหว่างสองวิธีนี้?"

ให้ความสนใจกับพฤติกรรมนี้:

A="A_VARIABLE"
echo "$(echo "\$A")"
echo "`echo "\$A"`"

คุณจะได้รับผลลัพธ์เหล่านี้:

$A
A_VARIABLE

 

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.