Bagaimana saya bisa menambahkan metode bantuan ke skrip shell?
128
Bagaimana cara saya memeriksa apakah suatu -hatribut telah dimasukkan ke dalam skrip shell? Saya ingin menampilkan pesan bantuan saat pengguna menelepon myscript.sh -h.
usage="$(basename "$0") [-h] [-s n] -- program to calculate the answer to life, the universe and everything
where:
-h show this help text
-s set the seed value (default: 42)"
seed=42while getopts ':hs:' option;docase"$option"in
h) echo "$usage"
exit
;;
s) seed=$OPTARG
;;:) printf "missing argument for -%s\n""$OPTARG">&2
echo "$usage">&2
exit 1;;
\?) printf "illegal option: -%s\n""$OPTARG">&2
echo "$usage">&2
exit 1;;esacdone
shift $((OPTIND -1))
Untuk menggunakan ini di dalam suatu fungsi:
gunakan "$FUNCNAME"sebagai ganti$(basename "$0")
tambahkan local OPTIND OPTARGsebelum menelepongetopts
Saya mencoba ini di dalam suatu fungsi, tetapi ketika saya mencoba menjalankan fungsinya saya mendapatkan kesalahan ini "basename: invalid option - 'b'". Sepertinya sedang mencoba meneruskan "-bash" ke basenamedengan tanda hubung utama.
Morgan Estes
5
apalagi fungsi gunakan "$FUNCNAME"tidak "$0". Juga, tambahkanlocal OPTIND OPTARG
glenn jackman
Terima kasih. FUNCNAMEbekerja. Saya memiliki semua fungsi saya di dalam satu file, jadi ini sempurna untuk memperluasnya menjadi sesuatu yang bermanfaat bagi orang lain.
Morgan Estes
5
@sigur, pastikan Anda mengutip "$usage"setiap tempat yang Anda gunakan.
glenn jackman
1
Untuk apa shift $((OPTIND - 1))?
hpaknia
45
Argumen pertama ke skrip shell tersedia sebagai variabel $1, sehingga implementasi yang paling sederhana adalah
Ya, meskipun OP tidak menentukan bash, dan [ini adalah versi yang sesuai dengan POSIX.
seb
Catatan - Untuk menggunakan di dalam function: Anda harus mengganti exit 0dengan returnjika Anda tidak ingin menghentikan shell Anda setelah menjalankan fungsi Anda. (Saya sudah pernah melakukannya sebelumnya)
Illuminator
29
di sini adalah bagian yang saya gunakan untuk memulai server VNC
#!/bin/bash
start(){
echo "Starting vnc server with $resolution on Display $display"#your execute command here mine is below#vncserver :$display -geometry $resolution}
stop(){
echo "Killing vncserver on display $display"#vncserver -kill :$display}########################## The command line help ##########################
display_help(){
echo "Usage: $0 [option...] {start|stop|restart}">&2
echo
echo " -r, --resolution run with the given resolution WxH"
echo " -d, --display Set on which display to host on "
echo
# echo some stuff here for the -a or --add-options
exit 1}################################# Check if parameters options ## are given on the commandline #################################while:docase"$1"in-r |--resolution)if[ $# -ne 0 ]; then
resolution="$2"# You may want to check validity of $2fi
shift 2;;-h |--help)
display_help # Call your function
exit 0;;-d |--display)
display="$2"
shift 2;;-a |--add-options)# do something here call function# and write it in your help function display_help()
shift 2;;--)# End of all options
shift
break;;-*)
echo "Error: Unknown option: $1">&2## or call function display_help
exit 1;;*)# No more optionsbreak;;esacdone###################### # Check if parameter ## is set too execute #######################case"$1"in
start)
start # calling function start();;
stop)
stop # calling function stop();;
restart)
stop # calling function stop()
start # calling function start();;*)# echo "Usage: $0 {start|stop|restart}" >&2
display_help
exit 1;;esac
Agak aneh bahwa saya menempatkan start stop restart dalam kasus yang terpisah tetapi harus bekerja
jika Anda memberikan opsi kosong ke -d; bukankah itu infinite loop?
zerobane
Mengapa Anda keluar 1 dalam fungsi pembantu?
jeantimex
17
Untuk solusi opsi tunggal cepat, gunakan if
Jika Anda hanya memiliki satu opsi untuk memeriksa dan itu akan selalu menjadi opsi pertama ( $1) maka solusi paling sederhana adalah ifdengan uji ( [). Sebagai contoh:
Perhatikan bahwa untuk kompatibilitas posix juga =akan berfungsi ==.
Mengapa mengutip $1?
Alasan $1perlunya dimasukkan dalam tanda kutip adalah bahwa jika tidak ada $1maka shell akan mencoba untuk menjalankan if [ == "-h" ]dan gagal karena ==hanya diberi satu argumen ketika mengharapkan dua:
$ [=="-h"]
bash:[:==: unary operator expected
Untuk penggunaan apa pun yang lebih kompleks getoptataugetopts
Seperti yang disarankan oleh orang lain , jika Anda memiliki lebih dari satu opsi sederhana, atau membutuhkan opsi Anda untuk menerima argumen, maka Anda harus menggunakan kompleksitas tambahan untuk menggunakangetopts .
Anda mungkin juga ingin mempertimbangkan getoptprogram alih-alih shell bawaan getopts. Ini memungkinkan penggunaan opsi panjang, dan opsi setelah argumen non opsi (misalnya, foo a b c --verbosebukan hanya foo -v a b c). Jawaban Stackoverflow ini menjelaskan cara menggunakan GNU getopt.
Jawaban:
inilah contoh untuk bash:
Untuk menggunakan ini di dalam suatu fungsi:
"$FUNCNAME"
sebagai ganti$(basename "$0")
local OPTIND OPTARG
sebelum menelepongetopts
sumber
basename
dengan tanda hubung utama."$FUNCNAME"
tidak"$0"
. Juga, tambahkanlocal OPTIND OPTARG
FUNCNAME
bekerja. Saya memiliki semua fungsi saya di dalam satu file, jadi ini sempurna untuk memperluasnya menjadi sesuatu yang bermanfaat bagi orang lain."$usage"
setiap tempat yang Anda gunakan.shift $((OPTIND - 1))
?Argumen pertama ke skrip shell tersedia sebagai variabel
$1
, sehingga implementasi yang paling sederhana adalahTapi apa yang dikatakan anubhava.
sumber
[
ini adalah versi yang sesuai dengan POSIX.function
: Anda harus menggantiexit 0
denganreturn
jika Anda tidak ingin menghentikan shell Anda setelah menjalankan fungsi Anda. (Saya sudah pernah melakukannya sebelumnya)di sini adalah bagian yang saya gunakan untuk memulai server VNC
Agak aneh bahwa saya menempatkan start stop restart dalam kasus yang terpisah tetapi harus bekerja
sumber
Untuk solusi opsi tunggal cepat, gunakan
if
Jika Anda hanya memiliki satu opsi untuk memeriksa dan itu akan selalu menjadi opsi pertama (
$1
) maka solusi paling sederhana adalahif
dengan uji ([
). Sebagai contoh:Perhatikan bahwa untuk kompatibilitas posix juga
=
akan berfungsi==
.Mengapa mengutip
$1
?Alasan
$1
perlunya dimasukkan dalam tanda kutip adalah bahwa jika tidak ada$1
maka shell akan mencoba untuk menjalankanif [ == "-h" ]
dan gagal karena==
hanya diberi satu argumen ketika mengharapkan dua:Untuk penggunaan apa pun yang lebih kompleks
getopt
ataugetopts
Seperti yang disarankan oleh orang lain , jika Anda memiliki lebih dari satu opsi sederhana, atau membutuhkan opsi Anda untuk menerima argumen, maka Anda harus menggunakan kompleksitas tambahan untuk menggunakan
getopts
.Sebagai referensi cepat, saya suka tutorial getopts 60 detik . †
Anda mungkin juga ingin mempertimbangkan
getopt
program alih-alih shell bawaangetopts
. Ini memungkinkan penggunaan opsi panjang, dan opsi setelah argumen non opsi (misalnya,foo a b c --verbose
bukan hanyafoo -v a b c
). Jawaban Stackoverflow ini menjelaskan cara menggunakan GNUgetopt
.† jeffbyrnes disebutkan bahwa link asli meninggal tapi untungnya mesin jalan kembali telah diarsipkan itu.
sumber
Lebih baik menggunakan fasilitas getopt dari bash. Silakan lihat Tanya Jawab ini untuk bantuan lebih lanjut: Menggunakan getop dalam skrip bash shell untuk mendapatkan opsi baris perintah yang panjang dan pendek
sumber
saya pikir Anda dapat menggunakan kasing untuk ini ...
sumber