私のスクリプトには、必須パラメータとともに複数のパラメータが含まれています。
while [ "$1" != "" ]; do
case $1 in
-f | --first ) shift
first=$1
;;
-s | --second ) shift
second=$1
;;
* ) break
esac
shift
done
echo "first: "$first" second: "$second
これはうまくいきます:
$ ./script.sh --first a --second b
first: a second: b
ただし、誰かがパラメータのパラメータを忘れた場合、パラメータを取得するのは間違っている可能性があります。
たとえば、次は機能しません。
$ ./script.sh --first --second a
first: --second second:
これは良くありません。最初はgetですが、2番目の強制は処理されません。
$ ./script.sh --first a --second
first: a second:
修正しようとしています。
* ) break
到着する:
* ) echo "Bad arguments"
exit 1
この場合、何が働くのか(強制が最初に処理されます):
$./script.sh --first --second b
Bad arguments
ただし、この場合は正しく機能しません(2番目の項目は処理しません)。
$ ./script.sh --first a --second
first: a second:
答え1
内蔵ケースを使用してくださいgetopts
。これは、すべての有効なオプション文字と引数が必要かどうかを一覧表示できるoptstringを使用します(オプション文字に続く:
)。たとえば、
while getopts 'f:s:' opt; do
case "$opt" in
f) first="$OPTARG" ;;
s) second="$OPTARG" ;;
:) usage 1 "-$OPTARG requires an argument" ;;
?) usage 1 "Unknown option '$opt'" ;;
esac
done
shift $((OPTIND -1))
--longオプションは組み込みgetopts
ではサポートされていません。これが要件の場合は、パッケージgetopt
のプログラムを使用してくださいutil-linux
。他のバージョンを使用しないでください。他のバージョンには重大な欠陥があります。
TEMP=$(getopt -o 'f:s:' --long 'first:,second:' -n "$0" -- "$@")
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
eval set -- "$TEMP"
while true ; do
case "$1" in
-f|--first) first="$2" ; shift 2 ;;
-s|--second) second="$2" ; shift 2 ;;
--) shift ; break ;;
*) echo 'Internal error!' ; exit 1 ;;
esac
done
メモ:
getopts
(s
)はPOSIXシェルに組み込まれており、移植可能で標準です。getopt
(nones
)は非標準で、いくつかの競合するバージョンがあり、ほとんどの場合、深刻な欠陥があります。util-linux
移植性を気にしない場合は、パッケージのバージョンを安全に使用できます。- 引数を必要とするオプションが指定されていない場合は、すべてエラーが発生します。
答え2
これは、イベントのテキストが何でも送信されるshift
ために発生します$2
。$1
スクリプトの正確な目的は不明ですが、たとえばこれを防ぐには、次のようにします。
while [[ "$1" != "" && "$2" != -* ]]; do
case $1 in
-f | --first ) shift
first=$1
;;
-s | --second ) shift
second=$1
;;
* ) break
esac
shift
done
echo "first: "$first" second: "$second
これにより、パラメーターが欠落している場合の操作が防止されます。
出力例:
$ ./script.sh --first a --second b
first: a second: b
$ ./script.sh --first --second b
first: second: