Saya mencoba untuk membangun skrip shell yang menerima berbagai opsi dan getopts
sepertinya solusi yang baik karena dapat menangani pemesanan variabel opsi dan argumen (saya pikir!).
Saya hanya akan menggunakan opsi pendek dan setiap opsi pendek akan membutuhkan nilai yang sesuai, misalnya: ./command.sh -a arga -g argg -b argb
tetapi saya ingin mengizinkan opsi dimasukkan dalam urutan non-spesifik, seperti cara kebanyakan orang terbiasa bekerja dengan perintah shell .
Poin lainnya adalah bahwa saya ingin melakukan pemeriksaan nilai argumen opsi saya sendiri, idealnya dalam case
pernyataan. Alasan untuk ini adalah bahwa pengujian saya :)
dalam case
pernyataan saya telah menghasilkan hasil yang tidak konsisten (mungkin karena kurangnya pemahaman di pihak saya).
Sebagai contoh:
#!/bin/bash
OPTIND=1 # Reset if getopts used previously
if (($# == 0)); then
echo "Usage"
exit 2
fi
while getopts ":h:u:p:d:" opt; do
case "$opt" in
h)
MYSQL_HOST=$OPTARG
;;
u)
MYSQL_USER=$OPTARG
;;
p)
MYSQL_PASS=$OPTARG
;;
d)
BACKUP_DIR=$OPTARG
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 2;;
:)
echo "Option -$OPTARG requires an argument" >&2
exit 2;;
esac
done
shift $((OPTIND-1))
echo "MYSQL_HOST='$MYSQL_HOST' MYSQL_USER='$MYSQL_USER' MYSQL_PASS='$MYSQL_PASS' BACKUP_DIR='$BACKUP_DIR' Additionals: $@"
Gagal untuk kejadian seperti ini ... ./command.sh -d -h
Ketika saya ingin flag -d sebagai membutuhkan argumen tapi saya mendapatkan nilai -d=-h
yang bukan yang saya butuhkan.
Jadi saya pikir akan lebih mudah untuk menjalankan validasi saya sendiri dalam laporan kasus untuk memastikan bahwa setiap opsi diatur dan ditetapkan hanya sekali.
Saya mencoba melakukan yang berikut tetapi if [ ! "$MYSQL_HOST" ]; then
blok saya tidak terpicu.
OPTIND=1 # Reset if getopts used previously
if (($# == 0)); then
echo "Usage"
exit 2
fi
while getopts ":h:u:p:d:" opt; do
case "$opt" in
h)
MYSQL_HOST=$OPTARG
if [ ! "$MYSQL_HOST" ]; then
echo "host not set"
exit 2
fi
;;
u)
MYSQL_USER=$OPTARG
if [ ! "$MYSQL_USER" ]; then
echo "username not set"
exit 2
fi
;;
p)
MYSQL_PASS=$OPTARG
if [ ! "$MYSQL_PASS" ]; then
echo "password not set"
exit 2
fi
;;
d)
BACKUP_DIR=$OPTARG
if [ ! "$BACKUP_DIR" ]; then
echo "backup dir not set"
exit 2
fi
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 2;;
#:)
# echo "Option -$opt requires an argument" >&2
# exit 2;;
esac
done
shift $((OPTIND-1))
echo "MYSQL_HOST='$MYSQL_HOST' MYSQL_USER='$MYSQL_USER' MYSQL_PASS='$MYSQL_PASS' BACKUP_DIR='$BACKUP_DIR' Additionals: $@"
Apakah ada alasan bahwa saya tidak dapat memeriksa apakah OPTARG
panjang nol dari dalam getopts ... while ... case
?
Apa cara yang lebih baik untuk menjalankan validasi argumen saya sendiri getopts
dalam kasus di mana saya tidak ingin bergantung pada :)
. Lakukan validasi argumen saya di luar while ... case ... esac
?
Lalu saya bisa berakhir dengan nilai argumen -d
dll dan tidak menangkap opsi yang hilang.
while
loop menjalankan opsi. Ini adalah metode yang telah saya gunakan seolah-olah itu verbose dibandingkan dengan yang lain, sangat jelas apa yang terjadi dalam naskah. Dan pemeliharaan oleh orang lain adalah penting dalam hal ini.