getopt
dan getopts
binatang buas yang berbeda, dan orang-orang tampaknya memiliki sedikit kesalahpahaman tentang apa yang mereka lakukan. getopts
adalah perintah bawaan untuk bash
memroses opsi baris perintah dalam satu lingkaran dan menetapkan masing-masing opsi dan nilai yang ditemukan pada gilirannya ke variabel bawaan, sehingga Anda dapat memprosesnya lebih lanjut. getopt
, bagaimanapun, adalah program utilitas eksternal, dan itu tidak benar-benar memproses pilihan Anda untuk Anda seperti yang dilakukan oleh bash getopts
, Getopt
modul Perl atau Python optparse
/ argparse
modules. Semua yang getopt
dilakukan adalah mengkanonik opsi yang diteruskan - yaitu mengonversikannya ke bentuk yang lebih standar, sehingga lebih mudah bagi skrip shell untuk memprosesnya. Misalnya, aplikasi getopt
mungkin mengonversi yang berikut:
myscript -ab infile.txt -ooutfile.txt
dalam hal ini:
myscript -a -b -o outfile.txt infile.txt
Anda harus melakukan pemrosesan aktual sendiri. Anda tidak harus menggunakan getopt
sama sekali jika Anda membuat berbagai batasan pada cara Anda dapat menentukan opsi:
- hanya menempatkan satu opsi per argumen;
- semua opsi berjalan sebelum parameter posisi apa pun (mis. argumen non-opsi);
- untuk opsi dengan nilai (mis. di
-o
atas), nilainya harus sebagai argumen terpisah (setelah spasi).
Kenapa menggunakan getopt
bukan getopts
? Alasan dasarnya adalah hanya GNU yang getopt
memberi Anda dukungan untuk opsi baris perintah yang telah lama dinamai. 1 (GNU getopt
adalah default di Linux. Mac OS X dan FreeBSD datang dengan dasar dan tidak terlalu berguna getopt
, tetapi versi GNU dapat diinstal; lihat di bawah.)
Sebagai contoh, berikut adalah contoh penggunaan GNU getopt
, dari skrip saya yang bernama javawrap
:
# NOTE: This requires GNU getopt. On Mac OS X and FreeBSD, you have to install this
# separately; see below.
TEMP=`getopt -o vdm: --long verbose,debug,memory:,debugfile:,minheap:,maxheap: \
-n 'javawrap' -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
VERBOSE=false
DEBUG=false
MEMORY=
DEBUGFILE=
JAVA_MISC_OPT=
while true; do
case "$1" in
-v | --verbose ) VERBOSE=true; shift ;;
-d | --debug ) DEBUG=true; shift ;;
-m | --memory ) MEMORY="$2"; shift 2 ;;
--debugfile ) DEBUGFILE="$2"; shift 2 ;;
--minheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MinHeapFreeRatio=$2"; shift 2 ;;
--maxheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MaxHeapFreeRatio=$2"; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
Ini memungkinkan Anda menentukan opsi suka --verbose -dm4096 --minh=20 --maxhe 40 --debugfi="/Users/John Johnson/debug.txt"
atau serupa. Efek dari panggilan ke getopt
adalah untuk mengkanoniskan opsi --verbose -d -m 4096 --minheap 20 --maxheap 40 --debugfile "/Users/John Johnson/debug.txt"
agar Anda dapat memprosesnya dengan lebih mudah. Mengutip sekitar "$1"
dan "$2"
penting karena memastikan bahwa argumen dengan spasi di dalamnya ditangani dengan benar.
Jika Anda menghapus 9 baris pertama (semuanya naik melalui eval set
baris), kodenya akan tetap berfungsi ! Namun, kode Anda akan lebih pemilih dalam jenis opsi apa yang diterimanya: Khususnya, Anda harus menentukan semua opsi dalam formulir "kanonik" yang dijelaskan di atas. getopt
Namun, dengan penggunaan , Anda dapat mengelompokkan opsi huruf tunggal, menggunakan bentuk opsi panjang yang tidak ambigu yang lebih pendek, menggunakan salah satu --file foo.txt
atau --file=foo.txt
gaya, menggunakan salah satu -m 4096
atau -m4096
gaya, menggunakan opsi atau gaya, mencampur pilihan dan non-opsi dalam urutan apa pun, dll. getopt
juga menampilkan pesan kesalahan jika opsi tidak dikenal atau ambigu ditemukan.
CATATAN : Sebenarnya ada dua versi yang sangat berbedagetopt
, dasar getopt
dan GNU getopt
, dengan fitur yang berbeda dan konvensi panggilan yang berbeda. 2 Basic getopt
cukup rusak: Tidak hanya tidak menangani opsi yang panjang, tetapi juga tidak bisa menangani ruang yang disematkan di dalam argumen atau argumen kosong, sedangkan getopts
melakukan ini dengan benar. Kode di atas tidak akan berfungsi di dasar getopt
. GNU getopt
diinstal secara default di Linux, tetapi pada Mac OS X dan FreeBSD perlu diinstal secara terpisah. Di Mac OS X, instal MacPorts ( http://www.macports.org ) dan kemudian lakukan sudo port install getopt
untuk menginstal GNU getopt
(biasanya ke /opt/local/bin
), dan pastikan itu /opt/local/bin
ada di jalur shell Anda di depan/usr/bin
. Di FreeBSD, instal misc/getopt
.
Panduan cepat untuk memodifikasi kode contoh untuk program Anda sendiri: Dari beberapa baris pertama, semua adalah "boilerplate" yang harus tetap sama, kecuali baris yang memanggil getopt
. Anda harus mengubah nama program setelah -n
, tentukan opsi pendek setelah -o
, dan opsi panjang setelah --long
. Beri tanda titik dua setelah opsi yang mengambil nilai.
Akhirnya, jika Anda melihat kode yang baru saja set
bukaneval set
, itu ditulis untuk BSD getopt
. Anda harus mengubahnya untuk menggunakan eval set
gaya, yang berfungsi dengan baik dengan kedua versi getopt
, sementara polos set
tidak berfungsi dengan baik dengan GNU getopt
.
1 Sebenarnya, getopts
dalam ksh93
mendukung opsi yang telah lama dinamai, tetapi shell ini tidak digunakan sesering bash
. Di zsh
, gunakan zparseopts
untuk mendapatkan fungsi ini.
2 Secara teknis, "GNU getopt
" adalah istilah yang salah; versi ini sebenarnya ditulis untuk Linux daripada proyek GNU. Namun, ia mengikuti semua konvensi GNU, dan istilah "GNU getopt
" umumnya digunakan (misalnya pada FreeBSD).