getoptdan getoptsbinatang buas yang berbeda, dan orang-orang tampaknya memiliki sedikit kesalahpahaman tentang apa yang mereka lakukan. getoptsadalah perintah bawaan untuk bashmemroses 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, Getoptmodul Perl atau Python optparse/ argparsemodules. Semua yang getoptdilakukan adalah mengkanonik opsi yang diteruskan - yaitu mengonversikannya ke bentuk yang lebih standar, sehingga lebih mudah bagi skrip shell untuk memprosesnya. Misalnya, aplikasi getoptmungkin 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 getoptsama 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
-oatas), nilainya harus sebagai argumen terpisah (setelah spasi).
Kenapa menggunakan getoptbukan getopts? Alasan dasarnya adalah hanya GNU yang getoptmemberi Anda dukungan untuk opsi baris perintah yang telah lama dinamai. 1 (GNU getoptadalah 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 getoptadalah 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 setbaris), 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. getoptNamun, dengan penggunaan , Anda dapat mengelompokkan opsi huruf tunggal, menggunakan bentuk opsi panjang yang tidak ambigu yang lebih pendek, menggunakan salah satu --file foo.txtatau --file=foo.txtgaya, menggunakan salah satu -m 4096atau -m4096gaya, menggunakan opsi atau gaya, mencampur pilihan dan non-opsi dalam urutan apa pun, dll. getoptjuga menampilkan pesan kesalahan jika opsi tidak dikenal atau ambigu ditemukan.
CATATAN : Sebenarnya ada dua versi yang sangat berbedagetopt , dasar getoptdan GNU getopt, dengan fitur yang berbeda dan konvensi panggilan yang berbeda. 2 Basic getoptcukup rusak: Tidak hanya tidak menangani opsi yang panjang, tetapi juga tidak bisa menangani ruang yang disematkan di dalam argumen atau argumen kosong, sedangkan getoptsmelakukan ini dengan benar. Kode di atas tidak akan berfungsi di dasar getopt. GNU getoptdiinstal 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 getoptuntuk menginstal GNU getopt(biasanya ke /opt/local/bin), dan pastikan itu /opt/local/binada 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 setbukaneval set , itu ditulis untuk BSD getopt. Anda harus mengubahnya untuk menggunakan eval setgaya, yang berfungsi dengan baik dengan kedua versi getopt, sementara polos settidak berfungsi dengan baik dengan GNU getopt.
1 Sebenarnya, getoptsdalam ksh93mendukung opsi yang telah lama dinamai, tetapi shell ini tidak digunakan sesering bash. Di zsh, gunakan zparseoptsuntuk 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).