私はこのbashコードをgetoptsと組み合わせて、getoptsを正しく理解したら、OPTINDには次のコマンドラインオプションのインデックスが含まれています。その場合は、私の言葉を訂正してください。私は間違っていますが、基本的に関数のローカル変数と同じ概念です。
それで、これによると、オプションが私に何の結果も与えない[-a somevalue ]
のはなぜですか?[-b somevalue ]
私は何が間違っていましたか?
OPT_A=A
OPT_B=B
while getopts :a:b FLAG; do
case $FLAG in
a)
OPT_A=$OPTARG
;;
b)
OPT_B=$OPTARG
;;
esac
done
shift $((OPTIND-1))
while [ $# -ne 0 ]; do
if [[ -z $OPT_A ]]; then
if [ `echo $1 | grep -o '\.' | wc -l` -ne 3 ]; then
echo "Parameter '$1' does not look like an IP Address (does not contain 3 dots).";
exit 1;
elif [ `echo $1 | tr '.' ' ' | wc -w` -ne 4 ]; then
echo "Parameter '$1' does not look like an IP Address (does not contain 4 octets).";
exit 1;
else
for OCTET in `echo $1 | tr '.' ' '`; do
if ! [[ $OCTET =~ ^[0-9]+$ ]]; then
echo "Parameter '$1' does not look like in IP Address (octet '$OCTET' is not numeric).";
exit 1;
elif [[ $OCTET -lt 0 || $OCTET -gt 255 ]]; then
echo "Parameter '$1' does not look like in IP Address (octet '$OCTET' in not in range 0-255).";
exit 1;
fi
done
fi
fi
if [[ -z $OPT_B ]]; then
if [[ "$2" =~ ^[0-9]+$ ]] && [ "$2" -ge 1 -a "$2" -le 10000 ]; then
echo "chosen variable: $2";
exit 1;
else echo "variable $2 is not in range '1 - 10000'";
exit 1;
fi
fi
done
exit 0
答え1
これは、すべてのロジックがそのうちの1つが空でなければ$OPT_[AB]
ならないためです。ただし、パラメータを渡さなくても引き続き-[ab] $OPTARG
使用できますOPT_[AB]=[AB]
。したがって、論理チェーンはルートを通過しません。
if [[ -z $OPT_A ]]; then...
...声明。
まあ..いいえみんなあなたの論理はこれに依存します。また、次のことをしています。
shift $((OPTIND-1))
while [ $# -ne 0 ]...
したがって、通過すると3に設定されscript -a arg
ます。だからあなたはgetopts
$OPT_A
arg
$OPTIND
shift 2
(すべての投稿)これによりテストはすぐに失敗しますwhile
。したがって、をcase
設定すると、$OPT_A
次に何が起こるかですexit 0
。だから$OPT_A
利用可能であることを確認していないようです。
それにもかかわらず、ほとんどのロジックはテスト失敗のために設計されているため、重要ではありません。しかし、スクリプトはただ exit
S. varを作成しました$OPT_A
が、何もしません。スクリプトの後、この値は使用できませんexit
。あらかじめ設定されたIPCはありませんが、ここにはそのようなものはありません。スクリプトはサブシェルから呼び出され、親シェルに戻ると設定した値は失われます。
さらに重要なのは:a:b
optstring$OPTARG
です-b
。 optstring の先行コロンは自動操作を示します。stderr
オプションまたはその引数に問題がある場合は記録されません。しかし、コロン続くオプション文字は、オプションに引数が必要であることを示します。良い:
while getopts :a:b: FLAG
...引数が必要な2つのオプションを表します。しかし、これは難しいかもしれません。引数を受け入れる必要があるとマークした後、getopts
引数がないことが確認された場合はエラーとして表示されるためです。
sh -c 'getopts :a:b: opt -a; echo "$opt $OPTARG"'
...印刷...
: a
この場合、オプションは最終的になります$OPTARG
。私たちがそれについてあまり沈黙していなければ、それはより明確になります。:
$opt
:
sh -c 'getopts a:b: opt -a; echo "$opt $OPTARG"'
No arg for -a option
:
したがって、コロンを確認する必要があります。?
これは通常、単純な内容を印刷するためにパスをリセットする別の種類のエラーです--help
。
$OPT_[AB]
個人的には、最初からそれらがすべて空であることを確認し、いくつかのロジックを実行して正しく設定し、テストループを完了して最後のテストを空にするように設定します。それらがまったく価値がない場合、それは私が扱わない何らかの理由であるに違いありません、とにかくバグです。これがテストループを実行する方法の始まりです...
param_err(){
set '' "$@"
: "${1:?Parameter '$OPTARG' does not look like an IP Address $2}"
}
test_oct(){
oIFS=$IFS; unset "${IFS+o}oIFS"; IFS=.
for oct in $1; do [ $oct -lt 256 ] ||
param_err "('$oct' too large)"
done; unset IFS oct
: "${oIFS+${IFS=$oIFS}}"
}
a_param()
case ${1##*.*.*.*.*} in (a) OPT_A=A;; #some default - no arg provided
(.*|*..*|*.) param_err '(empty octet)';;
(*[!.0-9]*) param_err '(octet is not positive integer)';;
(*.*.*.*) test_oct "$1"; OPT_A=$1;;
(*?*) param_err '(too few octets)';;
(*) param_err ${1:+"(too many octets)"} '(null param)';;
esac
unset OPT_A OPT_B
while getopts :a:b:c:d: opt
do case ${opt#:}$OPTARG in
a*) a_param "$OPTARG";;
b*) b_param "$OPTARG";; #tests as needed similar to a_param()
?*) help;; #param_err should call this too, but it just exits
esac
done
答え2
上部にシャバンラインがないため、使用中のシェル(sh
、dash
)がそれをサポートしていない可能性があります[[
。次のコマンドを使用してスクリプトを開始する必要があります。
#!/bin/bash
または他の場所bash
(これがシステムのbashパスではない場合type bash
)。
答え3
これを変更してみてください:while getopts:a:b FLAG do;
これを行うには:while getopts:a:b:FLAG;