Saat ini saya sedang menulis skrip Bash yang memiliki persyaratan sebagai berikut:
- itu harus dijalankan pada berbagai platform Unix / Linux
- itu harus mendukung opsi pendek dan pendek (GNU)
Saya tahu itu getopts
akan menjadi cara yang disukai dalam hal portabilitas tetapi AFAIK tidak mendukung opsi lama.
getopt
mendukung opsi panjang tetapi BashGuide sangat merekomendasikannya:
Jangan pernah gunakan getopt (1). getopt tidak dapat menangani string argumen kosong, atau argumen dengan spasi kosong. Tolong lupakan bahwa itu pernah ada.
Jadi, masih ada opsi penguraian manual. Ini rawan kesalahan, menghasilkan beberapa kode boilerplate, dan saya perlu menangani kesalahan sendiri (saya kira getopt(s)
melakukan penanganan kesalahan sendiri).
Jadi, apa pilihan yang lebih disukai dalam kasus ini?
bash
shell-script
options
user-interface
getopts
metode helpermet
sumber
sumber
Jawaban:
Jika harus portabel untuk berbagai Unices, Anda harus tetap berpegang pada POSIX sh. Dan AFAIU di sana Anda tidak punya pilihan selain menggulirkan penanganan argumen dengan tangan.
sumber
getopt
vsgetopts
tampaknya menjadi masalah agama. Adapun argumen terhadapgetopt
di FAQ Bash :"
getopt
tidak dapat menangani string argumen kosong" tampaknya merujuk pada masalah yang diketahui dengan argumen opsional , yang sepertinyagetopts
tidak mendukung sama sekali (setidaknya dari membacahelp getopts
untuk Bash 4.2.24). Dariman getopt
:Saya tidak tahu dari mana
getopt
argumen "... tidak dapat menangani [...] dengan ruang kosong tertanam" berasal, tapi mari kita coba ini:test.sh:
menjalankan:
Sepertinya memeriksa dan kawin dengan saya, tapi saya yakin seseorang akan menunjukkan bagaimana saya salah memahami kalimat itu. Tentu saja masalah portabilitas masih ada; Anda harus memutuskan berapa banyak waktu yang berharga untuk berinvestasi dalam platform dengan Bash yang lebih tua atau tidak tersedia. Kiat saya sendiri adalah dengan menggunakan pedoman YAGNI dan KISS - Hanya dikembangkan untuk platform spesifik yang Anda tahu akan digunakan. Portabilitas kode shell umumnya mencapai 100% seiring waktu pengembangan hingga tak terbatas.
sumber
getopt
Anda mengutip di sini adalah spesifik Linux. Catatan yanggetopt
bukan bagian daribash
, itu bahkan bukan utilitas GNU dan di Linux dikirimkan dengan paket util-linux.getopt
, hanya Linux AFAIK yang hadir dengan yang mendukung opsi panjang atau kosong dalam argumen. Yang lain hanya akan mendukung sintaks Sistem V.getopt
adalah perintah tradisional yang berasal dari Sistem V jauh sebelum Linux dirilis.getopt
tidak pernah distandarisasi. Tidak ada POSIX, Unix, atau Linux (LSB) yang pernah menstandardisasigetopt
perintah.getopts
ditentukan dalam ketiga tetapi tanpa dukungan untuk opsi panjang.getopt
. Ini adalah rasa linux-utils seperti yang ditunjukkan oleh @ StéphaneChazelas. Ini memiliki opsi lawas yang akan menonaktifkan sintaks yang dijelaskan di atas, khususnya halaman manual menyatakan "GETOPT_COMPATIBLE pasukan bisa menggunakan format panggilan pertama seperti yang ditentukan dalam SYNOPSIS". Namun jika Anda dapat mengharapkan sistem target untuk menginstal paket ini, ini benar-benar cara yang tepat, karena getopt asli buruk dan getopt Bash sangat terbatasAda getopts_long ini ditulis sebagai fungsi shell POSIX yang dapat Anda sematkan di dalam skrip Anda.
Perhatikan bahwa Linux
getopt
(dariutil-linux
) berfungsi dengan benar ketika tidak dalam mode tradisional dan mendukung opsi-opsi panjang, tetapi mungkin bukan opsi untuk Anda jika Anda perlu portabel ke Unix lain.Versi terbaru dari ksh93 (
getopts
) dan zsh (zparseopts
) memiliki dukungan bawaan untuk mem -parsing opsi-opsi panjang yang mungkin menjadi pilihan bagi Anda karena tersedia untuk sebagian besar Unices (meskipun sering tidak diinstal secara default).Opsi lain adalah menggunakan
perl
danGetopt::Long
modulnya yang keduanya harus tersedia di sebagian besar Unices saat ini, baik dengan menulis seluruh skripperl
atau hanya memanggil perl hanya untuk menguraikan opsi dan memberi makan informasi yang diekstrak ke shell. Sesuatu seperti:Lihat
perldoc Getopt::Long
apa yang dapat dilakukan dan bagaimana perbedaannya dari parser opsi lainnya.sumber
Setiap diskusi tentang masalah ini menyoroti opsi untuk menulis kode parsing secara manual - hanya dengan begitu Anda dapat yakin tentang fungsionalitas dan portabilitas. Saya menyarankan Anda untuk tidak menulis kode yang Anda dapat hasilkan dan hasilkan kembali oleh generator kode sumber terbuka yang mudah digunakan. Gunakan Argbash , yang telah dirancang untuk memberikan jawaban pasti untuk masalah Anda. Ini adalah generator kode yang terdokumentasi dengan baik tersedia sebagai aplikasi baris perintah , online atau sebagai gambar Docker .
Saya menyarankan agar perpustakaan bash, beberapa dari mereka menggunakan
getopt
(yang membuat sangat tidak dapat diakses) dan itu adalah rasa sakit untuk bundel gumpalan shell raksasa yang tidak dapat dibaca dengan skrip Anda.sumber
Anda bisa menggunakan
getopt
pada sistem yang mendukungnya dan menggunakan kembali untuk sistem yang tidak.Misalnya
pure-getopt
diimplementasikan dalam Bash murni untuk menjadi pengganti drop-in untuk GNUgetopt
.sumber