“ -” (เครื่องหมายขีดกลาง) สุดท้ายมีความหมายอย่างไรในตัวเลือกของ“ ทุบตี”?


15

ในบทช่วยสอนนี้เราต้องดำเนินการคำสั่งต่อไปนี้:

# curl -sL https://rpm.nodesource.com/setup_6.x | sudo -E bash -

สิ่งสุดท้าย-(ยัติภังค์) bashหมายถึงอะไร

ฉันเห็นคำสั่งจำนวนมากด้วยสิ่งนี้และไม่สามารถหาคำอธิบายที่สมเหตุสมผลได้และไม่พบวิธีปรับโครงสร้างการค้นหาของ Google มันเป็นเอาต์พุตของคำสั่ง piped หรือไม่?


5
คำถามเดียวกันกับถาม Ubuntu - ด้วยตัวอย่างเดียวกัน!
200_success

2
การดาวน์โหลดสิ่งต่าง ๆ จากเครือข่ายและนำไปวางเป็นsudo bashเสียงที่น่ากลัวจริงๆ ลองค้นหาบทช่วยสอนที่ไม่สนับสนุนการปฏิบัติเช่นนั้น
hmakholm ออกเดินทางจากโมนิกา

มันคือการสอนแบบ npm แต่ฉันเห็นด้วยกับคุณ ...
Omar BISTAMI

1
symbolhound.comหากคุณจำเป็นต้องค้นหาสิ่งที่มีสัญลักษณ์ในพวกเขาลอง
Joe

คำตอบ:


31

-พฤติกรรมทุบตีในทางที่ค่อนข้างไม่ได้มาตรฐานเมื่อมันมาถึง

POSIXพูดว่า:

หลักเกณฑ์ 10: อาร์กิวเมนต์
แรก--ที่ไม่ใช่ตัวเลือกอาร์กิวเมนต์ควรได้รับการยอมรับเป็นตัวคั่นที่ระบุถึงจุดสิ้นสุดของตัวเลือก อาร์กิวเมนต์ใด ๆ ต่อไปนี้ควรถือว่าเป็นตัวถูกดำเนินการแม้ว่าจะเริ่มต้นด้วย-อักขระ

[ ... ]

คำแนะนำที่ 13:
สำหรับยูทิลิตี้ที่ใช้ตัวถูกดำเนินการเพื่อเป็นตัวแทนของไฟล์ที่จะเปิดสำหรับการอ่านหรือการเขียน-ตัวถูกดำเนินการควรใช้เพื่อหมายถึงเฉพาะอินพุตมาตรฐาน (หรือเอาต์พุตมาตรฐานเมื่อชัดเจนจากบริบทที่ระบุไฟล์เอาต์พุต) หรือ -ชื่อไฟล์

และ

ในกรณีที่ยูทิลิตี้ที่อธิบายไว้ในปริมาตรเชลล์และยูทิลิตี้ของ POSIX.1-2017 ซึ่งสอดคล้องกับแนวทางเหล่านี้จำเป็นต้องยอมรับหรือไม่ยอมรับตัวถูกดำเนิน-การหมายถึงอินพุตหรือเอาต์พุตมาตรฐานการใช้งานนี้จะอธิบายไว้ในส่วน OPERANDS มิฉะนั้นถ้าใช้ยูทิลิตี้ดังกล่าวถูกดำเนินการเพื่อเป็นตัวแทนของไฟล์ก็คือการดำเนินการที่กำหนดไว้ไม่ว่าจะถูกดำเนินการ-ยืนสำหรับการป้อนข้อมูลมาตรฐาน (หรือออกมาตรฐาน) -หรือไฟล์ชื่อ

แต่man 1 bashอ่านแล้ว:

--สัญญาณสิ้นสุดของตัวเลือกและปิดการใช้งานการประมวลผลตัวเลือกต่อไป ข้อโต้แย้งใด ๆ หลังจากนั้น--จะถือว่าเป็นชื่อไฟล์และข้อโต้แย้ง ข้อโต้แย้งของเทียบเท่ากับ---

ดังนั้นสำหรับ Bash -หมายถึงอินพุตมาตรฐานหรือไฟล์ดังนั้นจึงค่อนข้างไม่ได้มาตรฐาน

ตอนนี้กรณีเฉพาะของคุณ:

curl -sL https://rpm.nodesource.com/setup_6.x | sudo -E bash -

ฉันสงสัยว่าผู้เขียนคำสั่งนี้อาจไม่ตระหนักว่า-เทียบเท่ากับ--ในกรณีนี้ ฉันสงสัยว่าผู้เขียนต้องการให้แน่ใจว่าbashจะอ่านจากอินพุตมาตรฐานของพวกเขาพวกเขาคาดว่า-จะทำงานตามแนวทางที่ 13

แต่แม้ว่ามันจะทำงานได้ตามแนวทาง-ก็จะไม่จำเป็นที่นี่เพราะbashตรวจพบเมื่ออินพุตมาตรฐานของมันเป็นท่อและทำตาม (ยกเว้น-cจะได้รับ ฯลฯ )

ยัง-ไม่ทำงานตามแนวทาง แต่ก็ใช้งาน--ได้ ยังคง--ไม่จำเป็นที่นี่เพราะไม่มีข้อโต้แย้งหลังจากนั้น

ในความคิดของฉันการ-เปลี่ยนแปลงครั้งสุดท้ายไม่มีอะไร คำสั่งจะใช้งานได้หากไม่มี

หากต้องการดูว่า--และ-มีประโยชน์โดยทั่วไปอย่างไรให้ศึกษาตัวอย่างด้านล่าง


catใน Kubuntu ของฉันเชื่อฟังแนวทางทั้งสองและฉันจะใช้มันเพื่อแสดงให้เห็นถึงประโยชน์ของและ---

ปล่อยให้มีชื่อไฟล์fooอยู่ สิ่งนี้จะพิมพ์ไฟล์:

cat foo

ปล่อยให้มีชื่อไฟล์--helpอยู่ สิ่งนี้จะไม่พิมพ์ไฟล์:

cat --help

แต่จะพิมพ์ไฟล์ชื่อ--help:

cat -- --help

สิ่งนี้จะต่อเชื่อมไฟล์ที่--helpมีชื่ออะไรก็ตามที่มาจากอินพุตมาตรฐาน:

cat -- --help -

ดูเหมือนว่าคุณไม่ต้องการจริงๆ--เพราะคุณสามารถส่งผ่าน./--helpซึ่งจะถูกตีความว่าเป็นไฟล์ได้อย่างแน่นอน แต่ให้พิจารณา

cat "$file"

เมื่อคุณไม่ทราบล่วงหน้าว่าเนื้อหาของตัวแปรคืออะไร คุณไม่สามารถเพิ่มเข้าไปเพียง./เพราะมันอาจเป็นเส้นทางที่แน่นอนและ./จะทำลายมัน ในทางกลับกันอาจเป็นไฟล์ชื่อ--help(เพราะเหตุใด) ในกรณี--นี้มีประโยชน์มาก นี่เป็นคำสั่งที่มีประสิทธิภาพมากขึ้น:

cat -- "$file"

6

ในman bashตอนท้ายของตัวเลือกอักขระเดียวมี: -

--    A -- signals the end of options and disables further option processing.
      Any arguments after the -- are treated as filenames and arguments. An
      argument of - is equivalent to --.

หากคุณอ้างถึงคำสั่งทั้งหมดฉันจะไม่เห็นเหตุผลที่จะใช้-หลังจากbashในกรณีนี้ แต่ไม่มีอันตรายใด ๆ


ขอบคุณสำหรับคำตอบใช่ฉันได้อ้างถึงคำสั่งทั้งหมด ดังนั้นหลังจาก - หรือ - จะไม่ถูกมองว่าเป็นตัวเลือก แต่เป็นชื่อไฟล์หรือการขัดแย้งคุณช่วยยกตัวอย่างที่มีประโยชน์ได้ไหม?
Omar BISTAMI

1
มันเป็นการอนุญาตให้สคริปต์ที่มีชื่อเริ่มต้น-มีข้อกำหนดที่ไม่น่าจะเกิดขึ้นได้ แต่-/ --ทำให้เป็นไปได้
AFH

1
@OmarBISTAMI การอ้างถึงคำสั่งจะส่งผลต่อวิธีที่เชลล์ขยาย แต่จะไม่มีผลกับอาร์กิวเมนต์ใด ๆ ที่ตามมา หากคุณขยายเครื่องหมายคำพูดรอบ ๆ อาร์กิวเมนต์ที่ถูกต้องจะทำให้พวกเขากลายเป็นส่วนหนึ่งของชื่อคำสั่งซึ่งไม่ใช่สิ่งที่คุณต้องการ มีบางคำสั่งที่ใช้ชื่อไฟล์เป็นอาร์กิวเมนต์ แต่ไม่ได้ใช้อินพุตมาตรฐานโดยค่าเริ่มต้น ตัวอย่างที่วางแผนไว้ช่วยให้คุณสามารถป้อนข้อมูลแซนวิช (จากเทอร์มินัลหรือไพพ์) ระหว่างสองไฟล์ cat file1 - file2 > file3.
Joe

1
curl -sL https://rpm.nodesource.com/setup_6.x | sudo -E bash -

bash -หมายความว่าbashกำลังรอ stdin ดังนั้นทุบตีจริงจะดำเนินการสิ่งที่ถูกส่งกลับโดยคำสั่งที่อยู่ด้านซ้ายของ|

ตัวอย่างที่คล้ายกัน แต่ง่ายกว่าคือ:

echo hello | cat - ที่นี่catจะพิมพ์ 'hello' ทำไม? เพราะ 'สวัสดี' ถูกส่งไปยังแมว|และcatกำลังรอสิ่งที่ส่งไป

ทีนี้มาแบ่งคำสั่งทั้งหมดเป็นสอง:

curl -sL https://rpm.nodesource.com/setup_6.x

คำสั่ง curl นี้จะส่งคืนสิ่งที่สามารถเข้าใจและดำเนินการโดย bash

แล้วเรามีท่อซึ่งจะส่งผลลัพธ์กลับโดยคำสั่งขดไปทางด้านขวาของท่อเช่น| sudo -E bash -ในที่สุดsudo -E bash -ทุบตีก็พร้อมที่จะดำเนินการอะไรก็ตามที่ถูกส่งไป

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