回答:
ではbash
、シェル、${!var}
変数間接です。名前がに保持されている変数の値に展開され$var
ます。
変数展開${var+value}
は、変数が設定されている場合(値が空であるかどうかに関係なく)に展開されるPOSIX拡張です。value
var
これらを組み合わせると、名前が保持されている変数が設定され${!var+x}
ているx
場合に展開$var
されます。
例:
$ foo=hello
$ var=foo
$ echo "${!var+$var is set, its value is ${!var}}"
foo is set, its value is hello
$ unset foo
$ echo "${!var+$var is set, its value is ${!var}}"
(出力として空の行)
問題の関数は、次のように短縮できます。
check_if_variable_is_set () { [ -n "${!1+x}" ]; }
あるいは:
check_if_variable_is_set () { [ -v "$1" ]; }
あるいは:
check_if_variable_is_set()[[ -v $1 ]]
名前付き変数が設定されている場合はtrue、それ以外の場合はfalseになる変数名のテスト-v
はどこにありbash
ますか。
POSIXly、それは書くことができます:
check_if_variable_is_set() { eval '[ -n "${'"$1"'+x}" ]'; }
その関数への引数が攻撃者の制御下に置かれる可能性がある場合、これらすべてが潜在的なコマンドインジェクションの脆弱性であることに注意してください。たとえばで試してくださいcheck_if_variable_is_set 'a[$(id>&2)]'
。
これを防ぐには、最初に引数が有効な変数名であることを確認する必要があります。変数の場合:
check_if_variable_is_set() {
case $1 in
("" | *[![:alnum:]_]* | [![:alpha:]_]*) false;;
(*) eval '[ -n "${'"$1"'+x}" ]'
esac
}
(ロケール[[:alpha:]]
でアルファベット文字をチェックすることに注意してください。一部のシェルは、変数に移植可能な文字セットのアルファベット文字しか受け入れません)