変数値を何かと比較するとき(算術比較をしようとするので使用できません。)"x$VAR" == "xyes"
いたずら)、変数に空白および/またはシェル構文が含まれているときにこれを防ぐ方法は何ですか?
$ (b="-z foo"; if [[ "$b" -eq 5 ]]; then echo foo; fi)
+(:50): b='-z foo'
+(:50): [[ -z foo -eq 5 ]]
-bash: [[: -z foo: syntax error in expression (error token is "foo")
試みられた:単一および二重括弧、算術評価((())
)、引用および引用されていない、"${b##-}"
さらに"${b@Q}"
確認された。https://mywiki.wooledge.org/BashPitfalls。
答え1
値が10進数でなければならず、ユーザーが混乱しているエラーやスクリプトの中断イベントが発生しないようにするには、変数に数値以外の文字が含まれているかどうかをテストし、独自のエラーメッセージとして処理します。
[[ -z ${val} ]] && {
echo "$0: Oops, \"${val}\" is empty" >&2
exit 1
}
[[ ${val} =~ [^[:digit:]] ]] && {
echo "$0: Oops, non-numeric characters found in \"${val}\"" >&2
exit 1
}
値が空白を必要としない文字列の場合は、同様の手法を使用して空白を確認します。
[[ ${val} =~ [[:blank:]] ]] && {
echo "$0: Oops, \"${val}\" contains space or tab characters" >&2
exit 1
}
改行、キャリッジリターン、フォームフィード、垂直タブもテストするには、[:space:]
文字クラスを使用してください。
これが私がbash v4.xスクリプトでやっていることです。他のシェルに対する提案はありません。
答え2
[[ ... ]]
ksh構成(bashを含むがバリアントを持つ一部のシェルによってコピーされます)では、算術演算子のオペランドは算術式として解釈されます。クリーンアップなしで外部から提供される入力を使用すると、ランダム実行の脆弱性が発生します。。
(( a == b ))
(kshでも)同じことが当てはまります。
[[ ... ]]
これを防ぐには、目的の入力と一致しない項目を手動で削除し、拒否または許可したい形式のみを許可する定数以外のコマンドを使用して、許可する入力を決定する必要があります。
bashや他のシェルでオプションの先頭記号と周囲のスペースを含む10進整数定数を許可したい場合は、10進整数のみを許可する組み込み関数[
とも呼ばれる機能を使用できます。test
[ "$b" -eq 5 ]
$b
10進整数定数でない場合、エラーは失敗し、[
状態2を返します。
すべてのPOSIX指定算術式定数(たとえば、12、-1、010、0x5)を許可するには、定数または空の文字列(オプションで囲まれたスペースで区切られた)が含まれている場合、算術式内でデフォルト変数のみを許可するアプローチを採用します。できdash
ます。
VAL="$b" dash -c '[ "$((VAL))" -eq 5 ]'
$b
(有効な定数が含まれていない場合、状態は再び2になります。)
1.123(一部のロケールおよび一部のawk実装では1,123の場合があります)、50e-1以上のようなより多くの数字を許可するには、次を使用できますawk
。
awk -- 'BEGIN{exit !(ARGV[1] == 5)}' "$b"
ここで$b
数値として認識されない場合は、文字列比較を実行してfalseを返します。 GNUを使用すると、awk
返されたかどうかを確認して、文字列が数値として認識されているかどうかを確認できます。typeof(ARGV[1])
strnum
また、範囲と精度にも注意を払ってください。 4.9999999999999999 または 18446744073709551621 (2 64 +5) は、要求する人に応じて 5 と同じと見なすことができます。