Dunno เกี่ยวกับgetopt
แต่getopts
builtin สามารถใช้ในการจัดการตัวเลือกยาวเช่นนี้:
while getopts :-: o
do case "$o$OPTARG" in
(-longopt1) process ;;
(-longopt2) process ;;
esac; done
แน่นอนเช่นเดียวกับที่ใช้ไม่ได้หากตัวเลือกแบบยาวควรมีอาร์กิวเมนต์ มันสามารถทำได้ แต่ แต่อย่างที่ฉันได้เรียนรู้การทำสิ่งนี้ ในขณะที่ฉันรวมมันไว้ที่นี่ในตอนแรกฉันรู้ว่าสำหรับตัวเลือกแบบยาวมันไม่มีประโยชน์มากนัก ในกรณีนี้มันทำให้case
(match)
ฟิลด์ของฉันสั้นลงด้วยอักขระที่คาดเดาได้เพียงตัวเดียว ตอนนี้สิ่งที่ฉันรู้คือมันยอดเยี่ยมสำหรับตัวเลือกสั้น ๆ - มันมีประโยชน์มากที่สุดเมื่อมันวนลูปมากกว่าสตริงที่มีความยาวไม่ทราบและเลือกไบต์เดียวตามตัวเลือกสตริง แต่เมื่อตัวเลือกคือหาเรื่องมีหลายสิ่งที่คุณทำด้วยfor var do case $var in
ชุดค่าผสมที่สามารถทำได้ ฉันคิดว่ามันดีกว่าเพื่อให้ง่าย
ฉันสงสัยว่ามันเป็นเรื่องจริงgetopt
แต่ฉันก็ไม่รู้พอที่จะพูดด้วยความมั่นใจ ที่กำหนดอาร์เรย์หาเรื่องต่อไปนี้ผมจะแสดงให้เห็นตัวเองเล็ก ๆ น้อย ๆ parser หาเรื่องฉัน - ซึ่งขึ้นอยู่กับความสัมพันธ์ที่ผิวเล็กน้อย / มอบหมายฉันได้มาชื่นชมสำหรับและalias
$((shell=math))
set -- this is ignored by default --lopt1 -s 'some '\''
args' here --ignored and these are ignored \
--alsoignored andthis --lopt2 'and
some "`more' --lopt1 and just a few more
นั่นคือสตริงหาเรื่องที่ฉันจะทำงานด้วย ขณะนี้:
aopts() { env - sh -s -- "$@"
} <<OPTCASE 3<<\OPTSCRIPT
acase() case "\$a" in $(fmt='
(%s) f=%s; aset "?$(($f)):";;\n'
for a do case "$a" in (--) break;;
(--*[!_[:alnum:]]*) continue;;
(--*) printf "$fmt" "$a" "${a#--}";;
esac;done;printf "$fmt" '--*' ignored)
(*) aset "" "\$a";;esac
shift "$((SHIFT$$))"; f=ignored; exec <&3
OPTCASE
aset() { alias "$f=$(($f${1:-=$(($f))+}1))"
[ -n "${2+?}" ] && alias "${f}_$(($f))=$2"; }
for a do acase; done; alias
#END
OPTSCRIPT
ซึ่งจะประมวลผลอาร์เรย์ของ ARG ในหนึ่งในสองวิธีที่แตกต่างกันขึ้นอยู่กับว่าคุณส่งชุดอาร์กิวเมนต์หนึ่งหรือสองชุด--
คั่นด้วยตัวคั่น ในทั้งสองกรณีมันใช้กับลำดับของการประมวลผลไปยังอาร์เรย์ ARG
ถ้าคุณเรียกว่าชอบ:
: $((SHIFT$$=3)); aopts --lopt1 --lopt2 -- "$@"
ลำดับแรกของธุรกิจคือการเขียนacase()
ฟังก์ชั่นให้มีลักษณะดังนี้:
acase() case "$a" in
(--lopt1) f=lopt1; aset "?$(($f)):";;
(--lopt2) f=lopt2; aset "?$(($f)):";;
(--*) f=ignored; aset "?$(($f)):";;
(*) aset "" "$a";;esac
และถัดshift 3
จาก การทดแทนคำสั่งในacase()
นิยามฟังก์ชันจะถูกประเมินเมื่อเชลล์การเรียกใช้สร้างอินพุตของเอกสารที่นี่ แต่acase()
จะไม่ถูกเรียกหรือกำหนดในเชลล์การเรียก มันถูกเรียกใน subshell แน่นอนและด้วยวิธีนี้คุณสามารถระบุตัวเลือกที่น่าสนใจในบรรทัดคำสั่งแบบไดนามิก
หากคุณมอบอาร์เรย์ยกเลิกคั่นมันก็ populates ตรงกับข้อโต้แย้งทั้งหมดเริ่มต้นด้วยสตริงacase()
--
ฟังก์ชั่นนี้จะทำการประมวลผลทั้งหมดใน subshell - จริง ๆ แล้วจะบันทึกค่าของ arg แต่ละตัวในนามแฝงที่กำหนดด้วยชื่อที่สัมพันธ์กัน เมื่อมันผ่านมันจะพิมพ์ออกมาทุกค่ามันบันทึกด้วยalias
- ซึ่งเป็น POSIX- ระบุในการพิมพ์ค่าที่บันทึกไว้ทั้งหมดที่ยกมาในลักษณะที่ค่าของพวกเขาสามารถนำกลับไปเปลือก ดังนั้นเมื่อฉันทำ ...
aopts --lopt1 --lopt2 -- "$@"
ผลลัพธ์ของมันจะเป็นดังนี้:
...ignored...
lopt1='8'
lopt1_1='-s'
lopt1_2='some '\'' args'
lopt1_3='here'
lopt1_4='and'
lopt1_5='just'
lopt1_6='a'
lopt1_7='few'
lopt1_8='more'
lopt2='1'
lopt2_1='and
some "`more'
ในขณะที่มันเดินผ่านรายการหาเรื่องมันจะตรวจสอบกับบล็อกกรณีสำหรับการแข่งขัน หากพบการแข่งขันตรงนั้นจะเป็นการโยนธง - f=optname
. จนกว่ามันจะพบตัวเลือกที่ถูกต้องอีกครั้งมันจะเพิ่มแต่ละอาร์กิวเมนต์ที่ตามมาลงในอาร์เรย์ที่สร้างขึ้นโดยอิงตามสถานะปัจจุบัน หากมีการระบุตัวเลือกเดียวกันหลายครั้งสารประกอบผลลัพธ์และจะไม่แทนที่ สิ่งใดที่ไม่ได้อยู่ในกรณี - หรืออาร์กิวเมนต์ใด ๆ ที่ตามตัวเลือกที่ถูกละเว้น - จะถูกกำหนดให้กับอาร์เรย์ที่ถูกละเว้น
เอาต์พุตเป็นแบบเชลล์ที่ปลอดภัยสำหรับเชลล์โดยอัตโนมัติโดยเชลล์ดังนั้น:
eval "$(: $((SHIFT$$=3));aopts --lopt1 --lopt2 -- "$@")"
... ควรจะปลอดภัยอย่างสมบูรณ์แบบ หากไม่ว่าด้วยเหตุผลใด ๆ ก็ตามไม่ปลอดภัยคุณก็ควรยื่นรายงานข้อผิดพลาดกับผู้ดูแลเชลล์ของคุณ
มันกำหนดค่านามแฝงสองชนิดสำหรับแต่ละการแข่งขัน ก่อนอื่นมันจะตั้งค่าสถานะ - สิ่งนี้เกิดขึ้นหรือไม่ตัวเลือกนำหน้าอาร์กิวเมนต์ที่ไม่ตรงกัน ดังนั้นการเกิดขึ้นของใด ๆในรายการหาเรื่องจะเรียก--flag
flag=1
นี้ไม่ได้สารประกอบ - เพิ่งได้รับ--flag --flag --flag
flag=1
ค่านี้จะเพิ่มขึ้นแม้ว่า - สำหรับอาร์กิวเมนต์ใด ๆ ที่อาจตามมา มันสามารถใช้เป็นคีย์ดัชนี หลังจากทำeval
ข้างต้นฉันสามารถทำ:
printf %s\\n "$lopt1" "$lopt2"
... เพื่อรับ ...
8
1
และอื่น ๆ :
for o in lopt1 lopt2
do list= i=0; echo "$o = $(($o))"
while [ "$((i=$i+1))" -le "$(($o))" ]
do list="$list $o $i \"\${${o}_$i}\" "
done; eval "printf '%s[%02d] = %s\n' $list"; done
เอาท์พุท
lopt1 = 8
lopt1[01] = -s
lopt1[02] = some ' args
lopt1[03] = here
lopt1[04] = and
lopt1[05] = just
lopt1[06] = a
lopt1[07] = few
lopt1[08] = more
lopt2 = 1
lopt2[01] = and
some "`more
และสำหรับ args ที่ไม่ตรงกับฉันจะแทนที่ละเว้นในfor ... in
ฟิลด์ด้านบนเพื่อรับ:
ignored = 10
ignored[01] = this
ignored[02] = is
ignored[03] = ignored
ignored[04] = by
ignored[05] = default
ignored[06] = and
ignored[07] = these
ignored[08] = are
ignored[09] = ignored
ignored[10] = andthis
getopts
แต่คุณกำลังใช้/usr/bin/getopt
คำสั่ง