現在、次の場所パラメータで使用するスクリプトがあります。
./script.sh fname lname address
また、提供したくない引数をスキップできるように、このスクリプトを呼び出すときに一般的なコマンドラインオプションをサポートしたいと思います。
./script.sh -f fname -a address
fname
唯一の必須パラメータです。
歴史的な理由と自動化のため、スクリプトは以前のバージョンと互換性があるはずです。
-f
これまでの私の推測では、文字列(スペースで囲まれている)を見つけることです。
- 見つかった場合、フラグを処理します。
- それ以外の場合は順次処理
flags='(\ |^)-f\ '
if [[ $* =~ $flags ]]; then
while [ $# -ne 0 ]
do
name="$1"
case "$name" in
-f)
shift
fname=$1
;;
-l)
shift
lname=$1
;;
-a)
shift
address=$1
;;
esac
shift
done
else
fname=${1}
lname=${2}
address=${3}
fi
ただし、ここでは正規表現を使用してオプションを確認する必要がありますが、これは信頼できない可能性があります。
コマンドラインオプションと位置パラメータを組み合わせる基本的な方法はありますか?
答え1
一般的なコマンドライン解析を実装するために使用されますgetopts
。この解析がトリガされたら、この事実を追跡するためのフラグを設定します。標準getopts
ループの後にフラグが設定されていない場合、前の動作が返されます。
以下のコードでは、フラグは変数ですnew_behavior
。
#!/bin/bash
# As written now, this should run without issues with
# /bin/sh too (there are no bash-isms in this code).
unset address
unset fname
unset lname
new_behavior=false
while getopts 'a:f:l:' opt; do
new_behavior=true
case $opt in
a)
address=$OPTARG
;;
f)
fname=$OPTARG
;;
l)
lname=$OPTARG
;;
*)
echo 'Error in command line parsing' >&2
exit 1
esac
done
shift "$(( OPTIND - 1 ))"
if ! "$new_behavior"; then
# Fall back on old behavior.
fname=$1; shift
lname=$1; shift
address=$1; shift
fi
if [ -z "$fname" ]; then
echo 'Missing mandatory argument "fname"' >&2
exit 1
fi
# The rest is unimportant to the actual command line parsing code
# and only here for your information and for debugging.
printf 'fname="%s", lname="%s", address="%s"\n' \
"$fname" "$lname" "$address"
if [ "$#" -gt 0 ]; then
printf 'Extra argument: "%s"\n' "$@"
fi
ユーザーがスクリプトの最初の引数としてオプションを指定すると、新しい動作がトリガーされます。オプションが有効かどうかは重要ではありません。
以前の動作テスト:
$ ./script eff ell addr
fname="eff", lname="ell", address="addr"
$ ./script eff ell addr "hello world"
fname="eff", lname="ell", address="addr"
Extra argument: "hello world"
$ ./script eff
fname="eff", lname="", address=""
$ ./script
Missing mandatory argument "fname"
$ ./script eff -l ell
fname="eff", lname="-l", address="ell"
新しい動作をテストします。
$ ./script -a addr -l ell -f eff
fname="eff", lname="ell", address="addr"
$ ./script -a addr -f eff "hello world"
fname="eff", lname="", address="addr"
Extra argument: "hello world"
$ ./script -f eff "hello world"
fname="eff", lname="", address=""
Extra argument: "hello world"
$ ./script -l eff "hello world"
Missing mandatory argument "fname"
$ ./script -f eff -- -l ell -f "eff again"
fname="eff", lname="", address=""
Extra argument: "-l"
Extra argument: "ell"
Extra argument: "-f"
Extra argument: "eff again"
(最後の例では、オプションではない追加の引数はoptionsから分離されており、--
2-l
番目の引数はすべて-f
オプションではありません。)
答え2
それでは、なぜ使用するのですかif
?パラメータを確認してください。
flaggiven=0
# This is very unsafe - use `getopt` or `getopts`. `shift` can fail - should be checked for errors.
while (($#)); do
case "$1" in
-f) fname=$2; flaggiven=1; shift; ;;
-l) lname=$2; flaggiven=1; shift; ;;
-a) address=$2; flaggiven=1; shift; ;;
*) break;
esac
shift
done
if (($# > 0)); then
if ((flaggiven)); then
echo "ERROR: you have given -f or -l or -a argument and arguments. One or the other, not both!"
exit 1
fi
fname=$1
lname=$2
address=$3
else
if ((!flaggiven)); then
echo "ERROR: you have to pass -f -l -a flags or pass 3 arguments"
exit 1
fi
fi