เหตุใดจึงเว้นช่องว่างระหว่างตัวเลือกและพารามิเตอร์


16

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

xargs -n 1

เป็นเช่นเดียวกับ

xargs -n1

แต่ถ้าคุณดูที่man pageตัวเลือกจะแสดงรายการเป็น-n max-argsซึ่งหมายความว่าควรจะรักษาพื้นที่ไว้ ไม่มีอะไรที่เกี่ยวกับรูปแบบย่อ -n เป็นสูงสุด args

นอกจากนี้ยังเกิดขึ้นกับสาธารณูปโภค Linux อื่น ๆ อีกมากมาย

สิ่งนี้เรียกว่าอะไรใน Linux? ยูทิลิตี้ทั้งหมดสนับสนุนรูปแบบย่อ (แต่ไม่เคยจัดทำเป็นเอกสารไว้ใน man page)?


1
12.1.2.aเป็นประวัติศาสตร์บางส่วน; ฉันสาบานว่าจะมีคำถามที่ดีเกี่ยวกับเรื่องนี้อยู่แล้ว แต่ฉันยังไม่พบมัน

2
@drewbenn คำถามอื่น ๆ ที่คุณคิดว่าอาจเป็นของฉัน: unix.stackexchange.com/q/188046/41515

คำตอบ:


12

เมื่อคุณเขียนบรรทัดคำสั่งในการแยกวิเคราะห์รหัสของคุณคุณจะต้องระบุว่าตัวเลือกใดที่มีอาร์กิวเมนต์และตัวเลือกใดไม่มี ตัวอย่างเช่นในเชลล์สคริปต์ยอมรับ-hตัวเลือก (สำหรับความช่วยเหลือเป็นต้น) และ-aตัวเลือกที่ควรโต้แย้ง

opt_h=0     # default value
opt_a=""

while getopts 'a:h' opt; do
    case $opt in
        h)  opt_h=1 ;;
        a)  opt_a="$OPTARG" ;;
    esac
done

echo "h: $opt_h"
echo "a: $opt_a"

a:hบิตกล่าวว่า "ผมคาดหวังว่าจะแยกสองตัวเลือก-aและ-hและ-aควรใช้อาร์กิวเมนต์" (มันเป็น:หลังจากaที่บอก parser ที่-aใช้เวลาอาร์กิวเมนต์)

ดังนั้นจึงไม่เคยมีความกำกวมใด ๆ ในกรณีที่ตัวเลือกสิ้นสุดลงซึ่งค่าของมันเริ่มต้นและที่อื่นจะเริ่มหลังจากนั้น

ใช้มัน

$ bash test.sh -h -a hello
h: 1
a: hello

$ bash test.sh -h -ahello
h: 1
a: hello

$ bash test.sh -hahello
h: 1
a: hello

นี่คือเหตุผลที่คุณใช้เวลาส่วนใหญ่ไม่ควรเขียนตัวแยกวิเคราะห์บรรทัดคำสั่งของคุณเองเพื่อแยกวิเคราะห์ตัวเลือก

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

$ bash test.sh -a hello -world
test.sh: illegal option -- w
test.sh: illegal option -- o
test.sh: illegal option -- r
test.sh: illegal option -- l
test.sh: illegal option -- d
h: 0
a: hello

การแก้ปัญหาต่อไปนี้:

$ bash test.sh -a hello -- -world
h: 0
a: hello

--สัญญาณสิ้นสุดของตัวเลือกบรรทัดคำสั่งและ-worldบิตที่เหลืออยู่สำหรับโปรแกรมที่จะทำสิ่งที่มันต้องการด้วย (มันในหนึ่งในตัวแปรตำแหน่ง)

rmนั่นคือโดยวิธีการวิธีการที่คุณเอาแฟ้มที่มีเส้นประในการเริ่มต้นของชื่อไฟล์ที่มีให้

แก้ไข :

โปรแกรมอรรถประโยชน์ที่เขียนในการโทร C getopt()(ประกาศในunistd.h) ซึ่งทำงานในลักษณะเดียวกัน ในความเป็นจริงสำหรับทุกสิ่งที่เรารู้ว่าbashฟังก์ชั่นอาจจะดำเนินการโดยใช้การเรียกฟังก์ชันgetopts C ห้องสมุด getopt()Perl, Python และภาษาอื่น ๆ มีการแยกวิเคราะห์บรรทัดคำสั่งที่คล้ายกันและเป็นไปได้มากว่ามันจะทำการแยกวิเคราะห์ด้วยวิธีที่คล้ายกัน

บางส่วนของรูทีนไลบรารี่getoptและgetoptเหมือนเหล่านี้ยังจัดการกับตัวเลือก "ยาว" ตัวเลือกเหล่านี้มักจะนำหน้าด้วย double-dash ( --) และตัวเลือกแบบยาวที่ใช้อาร์กิวเมนต์มักจะทำหลังจากมีเครื่องหมายเท่ากันตัวอย่างเช่น--block-size=SIZEตัวเลือกของ [การใช้งานบางอย่างของ] duยูทิลิตี้ (ซึ่งอนุญาตให้-B SIZEระบุสิ่งเดียวกัน)

คู่มือเหตุผลมักเขียนเพื่อแสดงช่องว่างระหว่างตัวเลือกสั้น ๆ และข้อโต้แย้งของพวกเขาอาจจะอ่านง่าย

แก้ไข : เครื่องมือเก่าจริงๆ เช่นddและtarยูทิลิตี้มีตัวเลือกโดยไม่ต้องมีเครื่องหมายขีดกลางอยู่ข้างหน้า นี่คือเหตุผลทางประวัติศาสตร์อย่างแท้จริงและเพื่อรักษาความเข้ากันได้กับซอฟต์แวร์ที่ต้องอาศัยการทำงานในลักษณะนั้น tarยูทิลิตี้ได้รับความสามารถในการใช้ตัวเลือกที่มีขีดกลางในครั้งล่าสุดเพิ่มเติม คู่มือ BSD สำหรับtarเรียกใช้ตัวเลือกแบบเก่าสำหรับ "การรวมธง"


คุณลักษณะนี้อาจใช้งานง่ายในการเขียนสคริปต์ทุบตี แต่ฉันคิดว่ายูทิลิตี้ส่วนใหญ่เขียนด้วยภาษาซี เหตุใดสาธารณูปโภคเหล่านี้จึงใช้คุณสมบัตินี้
J.Joe

@ J.Joe เพราะพวกเขาเรียกgetopt()(ประกาศไว้unistd.h) ซึ่งทำสิ่งเดียวกัน
Kusalananda

2
ใช่คุณพูดถูก การอ้างอิง สิ่งนี้ยังช่วยไขปริศนาที่สามารถรวมเข้าด้วยกันได้อีก-a -b=== -ab
J.Joe

1
อาร์กิวเมนต์ที่เป็นตัวเลือกสำหรับธงจะสร้างความกำกวมดังนั้นจึงไม่สามารถรวมกันได้ (หาก-aมีอาร์กิวเมนต์ที่เป็นตัวเลือก-abจะไม่เหมือนกัน-a -b) GNU getopt ไม่หยุดการประมวลผลแฟล็กเมื่อพบกับแฟล็กที่ไม่ใช่: แทน (โดยค่าเริ่มต้น) แต่จะเปลี่ยนสถานะไปที่ด้านหน้าของ argv แทน
ilkkachu

@ilkkachu ขอบคุณสำหรับคำชี้แจง ฉันอาจอัปเดตคำตอบของฉันในภายหลัง
Kusalananda

4

xargsเป็นหนึ่งในโปรแกรมอรรถประโยชน์ POSIX ตามที่คอมเมนต์โดย @drewbenn, POSIX จะจัดทำเอกสารพฤติกรรมการแยกวิเคราะห์ตัวเลือกสำหรับยูทิลิตี้ส่วนใหญ่ที่จะจับคู่getoptกับค่าใช้จ่ายบางอย่างสำหรับการใช้งานอื่น ๆ พูดใน12.1 ไวยากรณ์อาร์กิวเมนต์ยูทิลิตี้ :

ส่วนนี้จะอธิบายเกี่ยวกับไวยากรณ์อาร์กิวเมนต์ของยูทิลิตี้มาตรฐานและแนะนำคำศัพท์ที่ใช้ตลอด POSIX.1-2008 สำหรับการอธิบายอาร์กิวเมนต์ที่ประมวลผลโดยยูทิลิตี้

ภายใน POSIX.1-2008 มีการใช้สัญลักษณ์พิเศษเพื่ออธิบายไวยากรณ์ของอาร์กิวเมนต์ของยูทิลิตี้ เว้นแต่จะระบุไว้เป็นอย่างอื่นทุกรายละเอียดยูทิลิตี้ใช้สัญกรณ์นี้ซึ่งแสดงโดยตัวอย่างนี้ (ดู XCU ง่ายคำสั่ง ):

และสรุปด้วย

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

ภายใน POSIX (จำไว้ว่าครอบคลุมเฉพาะยูทิลิตี้ที่ใช้บ่อยที่สุด) มีข้อยกเว้นว่าตัวถูกดำเนินการผ่านซึ่งจะเป็นตัวเลือกในยูทิลิตี้อื่น ๆ เป็นพารามิเตอร์ตำแหน่งหรือพารามิเตอร์ที่มีไวยากรณ์พิเศษ :

POSIX อนุญาตให้มีตัวเลือก - ค่าตัวเลือก:

ตัวเลือกอาร์กิวเมนต์จะแสดงแยกออกจากตัวเลือกของพวกเขาด้วย<blank>ตัวละครยกเว้นเมื่อตัวเลือกอาร์กิวเมนต์ถูกล้อมรอบใน'['และ']'สัญกรณ์เพื่อระบุว่ามันเป็นตัวเลือก

โดยส่วนตัวฉันจำไม่ได้ว่ายูทิลิตี้ POSIX ใดใช้คุณสมบัตินี้ ncurses ticและinfocmpโปรแกรมอรรถประโยชน์ใช้คุณลักษณะสำหรับระดับของ-vตัวเลือก (verbose / debug)

จุดเฉพาะที่คุณถามเกี่ยวกับรายละเอียดในส่วนที่เหลือของวรรคนั้นเกิดขึ้นในหลายบรรทัด

ก่อน POSIX การใช้งานบางอย่างของpsตัวเลือกที่ยอมรับโดยไม่มีเครื่องหมายขีดคั่น คำอธิบาย POSIX ไม่ได้กล่าวถึงว่าในคำอธิบายของยูทิลิตี้หรือในเหตุผลไวยากรณ์:

นอกเหนือจาก POSIX แล้วยังมีการใช้งานตัวเลือกแบบยาว (เช่น GNU getopt_longหรือX Toolkit ) โดยใช้หลากหลายวิธีในการแยกหรือเข้าร่วมค่าของตัวเลือกกับตัวเลือก ตัวอย่างเช่นอาจใช้เครื่องหมายวรรคตอน:

--option=value
--option value

ขึ้นอยู่กับการนำไปใช้งาน, double-dash อาจ / อาจไม่ถูกใช้เพื่อแยกแยะตัวเลือกแบบยาวจาก short (getopt): lynxและ X Toolkit ใช้เส้นประเดียว; getopt_longตัวอย่างเช่นGNU ใช้เส้นประสองด้าน นอกจากนี้+อาจใช้เพื่อระบุว่าตัวเลือกถูกทำให้ไร้ผล

คำอธิบายของ POSIX ไม่ได้พูดถึงสิ่งเหล่านี้ แต่คุณมีแนวโน้มที่จะพบพวกเขาอย่างแน่นอน


คือ-option=valueควรจะเป็น--option=value(รูปแบบยาวตัวเลือกที่สองขีดกลางในการเริ่มต้นแทนการอย่างใดอย่างหนึ่ง)
J.Joe

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