การทำความเข้าใจ backtick (`)


35

ฉันลองคำสั่ง

$ b=5; echo `$b`;
-bash: 5: command not found

แต่จะไม่พิมพ์ 5 อย่างที่ควรจะเป็น สิ่งที่ฉันหายไปที่นี่?

`(backquote / backtick) หมายถึงอะไรในคำสั่ง? ดูเหมือนว่าจะ`ประเมินคำสั่งภายในและแทนที่พวกเขาด้วยการส่งออก


8
โปรดทราบว่าไม่แนะนำให้ทำการ backticks เนื่องจากคุณจะสูญเสียความสามารถในการแทนที่การดำเนินการซ้อน Insetad, $ (somecommand) เป็นที่ต้องการ ฉันช่วยปรับปรุงความสามารถในการอ่าน
Tommy

6
@ ทอมมี่, ไม่, backticks สามารถซ้อนกันได้ แต่มันก็กลายเป็นฝันร้ายที่หนีออกมาโดยเฉพาะเมื่อมีการอ้างถึงสองครั้งเช่นกัน
Stéphane Chazelas

คำตอบ:


52

ข้อความระหว่าง backticks จะถูกเรียกใช้งานและแทนที่ด้วยเอาต์พุตของคำสั่ง (ลบอักขระบรรทัดใหม่ต่อท้ายและระวังว่าพฤติกรรมของเชลล์จะแตกต่างกันไปเมื่อมีอักขระ NUL ในเอาต์พุต) ที่เรียกว่าการทดแทนคำสั่งเพราะมันถูกแทนที่ด้วยเอาท์พุทของคำสั่ง ดังนั้นหากคุณต้องการที่จะพิมพ์ 5 คุณไม่สามารถใช้ backticks คุณสามารถใช้เครื่องหมายคำพูดเหมือนecho "$b"หรือเพียงแค่วางคำพูดใด ๆ echo $bและการใช้งาน

อย่างที่คุณเห็นเนื่องจาก$bมี 5 เมื่อใช้ backticks bashพยายามเรียกใช้คำสั่ง5และเนื่องจากไม่มีคำสั่งดังกล่าวจึงล้มเหลวพร้อมข้อความแสดงข้อผิดพลาด

เพื่อให้เข้าใจถึงวิธีการทำงานของแบ็คทริคให้ลองใช้วิธีนี้:

$ A=`cat /etc/passwd | head -n1`
$ echo "$A"

cat /etc/passwd |head -n1ควรพิมพ์บรรทัดแรกของ/etc/passwdไฟล์ แต่เนื่องจากเราใช้ backticks จึงไม่พิมพ์บนคอนโซล แต่จะเก็บไว้ในAตัวแปรแทน คุณสามารถสะท้อน$Aถึงสิ่งนี้ โปรดทราบว่าวิธีที่มีประสิทธิภาพมากขึ้นในการพิมพ์บรรทัดแรกคือการใช้คำสั่งhead -n1 /etc/passwdแต่ฉันต้องการชี้ให้เห็นว่าการแสดงออกภายใน backticks นั้นไม่จำเป็นต้องง่าย

ดังนั้นถ้าบรรทัดแรกของ / etc / passwd เป็นคำสั่งแรกจะถูกแทนที่แบบไดนามิกโดยทุบตีไปroot:x:0:0:root:/root:/bin/bashA="root:x:0:0:root:/root:/bin/bash"

โปรดทราบว่าไวยากรณ์นี้เป็นของเชลล์เป้าหมาย การเขียนและหลบหนีกลายเป็นฝันร้ายอย่างรวดเร็วโดยเฉพาะเมื่อคุณเริ่มทำรัง Ksh แนะนำ$(...)ทางเลือกซึ่งตอนนี้เป็นมาตรฐาน ( POSIX ) และสนับสนุนโดยเชลล์ทั้งหมด (แม้แต่เชลล์เป้าหมายจาก Unix v9) ดังนั้นคุณควรใช้$(...)แทนทุกวันนี้เว้นแต่คุณจะต้องพกพาไปได้ที่บอร์นเชลล์เก่ามาก

โปรดทราบว่าเอาต์พุตของ`...`และ$(...)อาจมีการแยกคำและสร้างชื่อไฟล์เช่นการขยายตัวตัวแปร (ใน zsh, การแยกคำเท่านั้น) ดังนั้นโดยทั่วไปจะต้องมีการยกมาในรายการบริบท


1
สวัสดี @Krzysztof ที่เป็นประโยชน์! "ตั้งแต่ $ b มี 5, bash พยายามเรียกใช้คำสั่ง 5" เป็นสิ่งที่ฉันกำลังมองหา
coolcric

you can use quotation marks, like echo "$b"=> "" ทำอะไรเป็นพิเศษหรือไม่ ดูเหมือนว่าecho $bจะใช้งานได้เช่นกัน
Tootsie Rolls

@Anita: ในเครื่องหมายคำพูดทั่วไปทำสิ่งพิเศษบางอย่าง (มันเปลี่ยนวิธีการรักษาตัวละครพิเศษ - โดยเฉพาะอย่างยิ่งพื้นที่สีขาว) แต่ในกรณีนี้พวกเขาสามารถลดลงได้โดยไม่มีปัญหามาก นี่เป็นเพราะไม่มีการใช้อักขระพิเศษและechoคำสั่งไม่สนใจจำนวนอาร์กิวเมนต์ที่ได้รับดังนั้นหากbมีช่องว่างบางส่วนภายในจะได้รับอาร์กิวเมนต์หลายตัวและจะพิมพ์ออกมา นี่อาจไม่เป็นกรณีสำหรับคำสั่งอื่น ๆ (โดยเฉพาะเมื่อไม่ได้ตั้งค่าตัวแปร) ดังนั้นฉันมักจะล้อมรอบตัวแปรด้วยเครื่องหมายคำพูดเสมอ
Krzysztof Adamski

จะดีถ้า(POSIX)เป็นลิงค์ไปยังมาตรฐานจริง
erikbwork

1
@ erikb85: บันทึกนี้ก็ไม่ได้เพิ่มขึ้นโดยฉัน แต่ฉันได้แก้ไขด้วยการเชื่อมโยงตามที่คุณแนะนำ :)
ซีส Adamski

11

Backtick ทำสิ่งที่คุณพูดอย่างแน่นอน คุณตั้งค่าตัวแปรเป็นจำนวนเต็ม เมื่อคุณวางตัวแปรนั้นไว้ใน backticks bash จะพยายามเรียกใช้มันเป็นคำสั่ง เนื่องจากไม่ใช่คำสั่งคุณจะได้รับข้อผิดพลาดที่คุณเห็น

สิ่งที่คุณต้องการทำคือ:

$ b=5; echo $b

หากต้องการทำความเข้าใจ backticks ให้ดีขึ้นเปรียบเทียบกับ:

$ b=5; a=`echo $b`; echo $a
  5

8

การอธิบายอย่างเป็นขั้นเป็นตอนควรอธิบายให้เข้าใจ

$ b=5; echo `$b`;
  1. ตั้งค่าตัวแปรbเป็น 5
  2. ประเมิน$b(ทำงานอย่างมีประสิทธิภาพ5)
  3. echoเป็นผลลัพธ์ของการประเมินผลข้างต้น

ใช่แล้วผลลัพธ์ที่คุณได้รับคาดว่าจะได้ คุณกำลังประเมินเนื้อหาของตัวแปรไม่ใช่คำสั่งจริงที่คุณคิดว่าเป็น ทุกสิ่งที่คุณใส่ไว้ใน backticks นั้นจะถูกประเมินโดย simplay (runned) ในเชลล์ (sub) ใหม่


สวัสดี @ gertvdijk ขอบคุณสำหรับการโพสต์ของคุณ! ฉันคิดว่า `คืนสิ่งที่เหลืออยู่หลังจากประเมินเนื้อหา ดังนั้นฉันคิดว่า `$ b 'จะได้ 5 คืนสำหรับ echo เพื่อพิมพ์
coolcric
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.