หมายความว่าอย่างไรในเชลล์เมื่อเราใส่คำสั่งไว้ในเครื่องหมายดอลลาร์และวงเล็บ: $ (คำสั่ง)


111

ฉันแค่ต้องการเข้าใจบรรทัดของโค้ดต่อไปนี้ในเชลล์ ใช้เพื่อรับไดเร็กทอรีการทำงานปัจจุบัน ฉันทราบว่า$(variable)ชื่อส่งคืนค่าภายในชื่อตัวแปร แต่$(command)ควรส่งคืนอะไร มันคืนค่าหลังจากรันคำสั่งหรือไม่? ในกรณีนั้นเราสามารถใช้`เพื่อดำเนินการคำสั่ง

CWD="$(cd "$(dirname $0)"; pwd)"

ผลลัพธ์เดียวกันสามารถนำมาจากบรรทัดของโค้ดต่อไปนี้และในเชลล์เวอร์ชันอื่น

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

ฉันไม่สามารถเข้าใจความหมายของและ$(cd..$(dirname

ใครช่วยฉันคิดว่าคำสั่งนี้ดำเนินการอย่างไร


1
และนี่คือคำถามเกี่ยวกับข้อดี / ข้อเสียของ$()vs. ``: stackoverflow.com/questions/9449778/…
ไม่มี

คำตอบ:


115

การใช้สิ่งที่$คล้ายกัน${HOME}จะให้คุณค่าของ HOME การใช้วิธีการ$like $(echo foo)เรียกใช้สิ่งที่อยู่ในวงเล็บใน subshell และส่งคืนค่านั้นเป็นค่า ในตัวอย่างของฉันคุณจะได้รับfooตั้งแต่echoนั้นมาจะเขียนfooถึงมาตรฐาน


37
ใช่; $(...)เป็นวิธีการเขียนคำสั่งที่ดีกว่าการพยายามใช้ back quotes พิจารณาการเขียน: gcclib=$(dirname $(dirname $(which gcc)))/libใช้ back quotes ก่อนที่คุณจะประสบความยากลำบากในการทำใน Markdown มันยากกว่าเพราะคุณต้องหนี backquotes ของคำสั่งที่ซ้อนกันในขณะที่คุณไม่ได้ใช้$(...)สัญกรณ์
Jonathan Leffler

7
ในทางเทคนิค$(echo foo)สร้างการทดแทนคำสั่งไม่ใช่ subshell คำตอบอื่น ๆ ในปัจจุบันได้รับสิทธินี้ ฉันคิดว่าการแทนที่คำสั่งนั้นทำงานใน subshell เรียงลำดับ แต่ยังคงเป็นแนวคิดที่แตกต่างกัน
trysis

4
@trysis - การแทนที่คำสั่งทำงานใน subshell อย่างแน่นอนดังนั้นจึงควรสังเกต
Eliran Malka

2
ฉันเข้าใจว่า backticks ให้ผลลัพธ์เช่นเดียวกับ $ () แต่ความแตกต่างคือเครื่องสำอางอย่างแท้จริงหรือไม่? มีเหตุผลที่จะใช้อย่างใดอย่างหนึ่งกับอีกข้อหนึ่งนอกเหนือจากที่ $ () อ่านได้ชัดเจนกว่า?
Mitchell Tracy

2
"การใช้ $ like $ (echo foo) หมายถึงเรียกใช้สิ่งที่อยู่ในวงเล็บใน subshell และคืนค่านั้นเป็นค่า" ... สิ่งนี้สับสนเนื่องจากคำสั่งนี้$(echo foo)จะพยายามเรียกใช้สิ่งที่ส่งคืนจากวงเล็บคำสั่งนี้จะทำงานก่อนecho fooจากนั้นจะพยายามเรียกใช้fooซึ่งทำให้เกิดข้อผิดพลาด
Accountant م

21
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

ใครช่วยฉันคิดว่าคำสั่งนี้ดำเนินการอย่างไร

มาดูส่วนต่างๆของคำสั่ง BASH_SOURCEเป็นตัวแปร bash array ที่มีชื่อไฟล์ต้นทาง ดังนั้น"${BASH_SOURCE[0]}"จะคืนชื่อไฟล์สคริปต์ให้คุณ

dirnameเป็นยูทิลิตี้ที่จัดทำโดย GNU coreutils ที่ลบส่วนประกอบสุดท้ายออกจากชื่อไฟล์ ดังนั้นหากคุณรันสคริปต์ของคุณด้วยการพูดว่าbash foo, จะกลับมา"$( dirname "${BASH_SOURCE[0]}" )" .ถ้าคุณบอกว่าbash ../fooมันจะกลับมา..; สำหรับมันต้องการกลับbash /some/path/foo/some/path

ในที่สุดคำสั่งทั้งหมด"$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"จะได้รับไดเร็กทอรีสัมบูรณ์ที่มีสคริปต์ที่ถูกเรียกใช้

$(...) อนุญาตให้มีการทดแทนคำสั่งกล่าวคืออนุญาตให้เอาต์พุตของคำสั่งแทนที่คำสั่งนั้นเองและสามารถซ้อนกันได้


1
ขอโทษที่ไปงานปาร์ตี้ช้าไป 3 ปี แต่คุณช่วยอธิบายได้ไหมว่าทำไมคำสั่งนี้ถึงได้ผล คุณกล่าวว่าdirnameส่งคืนพา ธ ของไฟล์ที่เรียกใช้งาน (สัมพัทธ์หรือสัมบูรณ์กับไดเร็กทอรีการทำงานปัจจุบัน) cdเปลี่ยน pwd เป็นไดเร็กทอรีนั้นและpwdพิมพ์พา ธ สัมบูรณ์ของไดเร็กทอรีการทำงานปัจจุบัน แต่ทำไมพวกเขาถึงเข้าร่วมด้วย&&? และจะDIRยึดอะไรหากcdล้มเหลว?
Christian

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