Tidak tahu tentang getopt
tetapi getopts
builtin dapat digunakan untuk menangani hanya opsi panjang seperti ini:
while getopts :-: o
do case "$o$OPTARG" in
(-longopt1) process ;;
(-longopt2) process ;;
esac; done
Tentu saja, sebagaimana adanya, itu tidak berfungsi jika opsi-opsi panjang seharusnya memiliki argumen. Itu bisa dilakukan, tetapi, karena saya sudah belajar mengerjakan ini. Sementara saya awalnya termasuk di sini saya menyadari bahwa untuk opsi lama tidak memiliki banyak utilitas. Dalam hal ini hanya memperpendek case
(match)
bidang saya dengan satu karakter yang dapat diprediksi. Sekarang, yang saya tahu, itu sangat baik untuk opsi pendek - ini sangat berguna ketika looping pada string yang panjangnya tidak diketahui dan memilih byte tunggal sesuai dengan option-string-nya. Tetapi ketika pilihannya adalah arg, tidak banyak yang Anda lakukan dengan for var do case $var in
kombinasi yang bisa dilakukan. Lebih baik, saya pikir, untuk membuatnya tetap sederhana.
Saya menduga hal yang sama berlaku getopt
tetapi saya tidak cukup tahu tentang hal itu untuk mengatakan dengan pasti. Dengan susunan arg berikut, saya akan menunjukkan parser arg kecil saya sendiri - yang terutama tergantung pada hubungan evaluasi / penugasan yang saya hargai untuk alias
dan $((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
Itulah string arg yang akan saya gunakan. Sekarang:
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
Itu memproses array arg dalam salah satu dari dua cara berbeda tergantung pada apakah Anda menyerahkannya satu atau dua set argumen yang dipisahkan oleh --
pembatas. Dalam kedua kasus itu berlaku untuk urutan pemrosesan ke array arg.
Jika Anda menyebutnya seperti:
: $((SHIFT$$=3)); aopts --lopt1 --lopt2 -- "$@"
Urutan pertama bisnisnya adalah menulis acase()
fungsinya agar terlihat seperti:
acase() case "$a" in
(--lopt1) f=lopt1; aset "?$(($f)):";;
(--lopt2) f=lopt2; aset "?$(($f)):";;
(--*) f=ignored; aset "?$(($f)):";;
(*) aset "" "$a";;esac
Dan di sebelah shift 3
. Substitusi perintah dalam acase()
definisi fungsi dievaluasi ketika shell panggilan membangun input fungsi di sini-dokumen, tetapi acase()
tidak pernah dipanggil atau didefinisikan dalam shell panggilan. Meskipun demikian, ini disebut dalam subkulit, jadi dengan cara ini Anda dapat menentukan opsi menarik secara dinamis pada baris perintah.
Jika Anda memberikannya array yang tidak dibatasi itu hanya diisi acase()
dengan kecocokan untuk semua argumen yang dimulai dengan string --
.
Fungsi ini praktis memproses semua dalam subkulit - iteratif menyimpan masing-masing nilai arg ke alias ditugaskan dengan nama asosiatif. Ketika itu melalui itu mencetak setiap nilai yang disimpan dengan alias
- yang POSIX ditentukan untuk mencetak semua nilai yang disimpan dikutip sedemikian rupa sehingga nilai-nilai mereka dapat dikembalikan ke shell. Jadi ketika saya melakukannya ...
aopts --lopt1 --lopt2 -- "$@"
Outputnya terlihat seperti ini:
...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'
Saat berjalan melalui daftar arg itu memeriksa blok kasus untuk pertandingan. Jika menemukan kecocokan di sana ia melempar bendera - f=optname
. Sampai sekali lagi menemukan opsi yang valid itu akan menambahkan setiap argumen berikutnya ke array yang dibangun berdasarkan bendera saat ini. Jika opsi yang sama ditentukan beberapa kali hasilnya akan bertambah dan tidak menimpa. Apa pun yang tidak dalam kasus - atau argumen berikut opsi yang diabaikan - ditugaskan ke array yang diabaikan .
Outputnya diamankan dengan shell untuk input shell secara otomatis oleh shell, dan karenanya:
eval "$(: $((SHIFT$$=3));aopts --lopt1 --lopt2 -- "$@")"
... harus benar-benar aman. Jika karena alasan apa pun tidak aman, maka Anda mungkin harus mengajukan laporan bug dengan pengelola shell Anda.
Ini menetapkan dua jenis nilai alias untuk setiap pertandingan. Pertama, ia menetapkan sebuah bendera - ini terjadi terlepas dari suatu opsi mendahului argumen yang tidak cocok. Jadi setiap kejadian --flag
dalam daftar arg akan memicu flag=1
. Ini tidak majemuk - --flag --flag --flag
hanya mendapat flag=1
. Nilai ini memang bertambah - untuk setiap argumen yang mungkin mengikutinya. Ini dapat digunakan sebagai kunci indeks. Setelah melakukan hal di eval
atas saya dapat melakukan:
printf %s\\n "$lopt1" "$lopt2"
...mendapatkan...
8
1
Dan sebagainya:
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
KELUARAN
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
Dan untuk argumen yang tidak cocok saya akan mengganti diabaikan di for ... in
bidang di atas untuk mendapatkan:
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
, tetapi Anda menggunakan/usr/bin/getopt
perintah.