Bashで単項テストを使用する条件式は、-v myvariable
変数がmyvariable
設定されているかどうかをテストします。myvariable
ドルを前に付けて拡張しないでください。いいえ $myvariable
。これで、配列要素の場合、条件式は-v myarray[index]
完全な拡張構文なしでうまく機能することがわかりました${myarray[$index]}
。この試み:
myarray[2]=myvalue
for i in 1 2 3
do
[ -v myarray\[i] ] && echo element $i is set
done
\[
(引用符を使用する代わりにワイルドカードを防ぐためにエスケープ処理に注意してください)
希望の出力を提供します。
element 2 is set
質問 この動作を使用しても安全ですか?また〜として知られていますこれは文書化された動作ですか?
付録 回答を読んだ後https://unix.stackexchange.com/a/677920/376817Stéphane Chazelasの例を拡張しました。
myarray[1]=val myarray[2]=val myarray[3]=val myarray[4]=val myarray[5]=val myarray[6]="" myarray[2]=""
unset myarray[3] myarray[4] myarray[5]
touch myarray4 myarrayi
myarray4=val myarrayi=val
それから
for i in {0..7}; do [ -v myarray\[i] ] && echo element $i is set; done
与えられた
element 1 is set
element 2 is set
element 6 is set
インデックス式を引用またはエスケープしないでください[i]
。
for i in {0..7}; do [ -v myarray[i] ] && echo element $i is set; done
与えられた
element 0 is set
element 1 is set
element 2 is set
element 3 is set
element 4 is set
element 5 is set
element 6 is set
element 7 is set
変数unsetと同じmyarrayi
:
unset myarrayi
for i in {0..7}; do [ -v myarray[i] ] && echo element $i is set; done
与えられた
%nothing%
最後に、インデックスを次に展開します$i
(まだ角かっこを引用またはエスケープしません)。
for i in {0..7}; do [ -v myarray[$i] ] && echo element $i is set; done
それを与える
element 1 is set
element 2 is set
element 4 is set
なぜなら
ls -l myarray*
プログラム
-rw-rw-r-- 1 me us 0 nov 17 15:37 myarray4
-rw-rw-r-- 1 me us 0 nov 17 15:37 myarrayi
答え1
では、bash
次のことができます。
[ -v 'a[2]' ]
または
[[ -v a[2] ]]
インデックス2の配列要素またはキー「2」の連想配列要素が設定されているかどうかをテストするには(空の文字列にもかかわらず)、次の点に注意してください。
[
(別名)コマンドを使用するときはワイルドカードなので、引用符と文字がtest
必要です。これは通常のコマンドであるため、他の一般的なコマンドのように解釈されるため、inはorと同じように拡張されます。現在の作業ディレクトリに呼び出されたファイルがある場合は、そのファイルに展開されます。そうでない場合は、有効または空の状態に展開されるか、それぞれエラーが発生します。独自の構文を持つ特殊構造なので問題ありません。[
]
[
a[2]
[ -v a[2] ]
ls -d a[2]
unset a[2]
a2
a[2]
nullglob
failglob
a[2]
[[ ... ]]
連想配列(テスト済みバージョン5.1以降)の場合、検証するキーが変数にある場合は、最新バージョンで導入されたオプションだけでなく、またはが
$i
必要です。[ -v 'a[$i]' ]
[[ -v 'a[$i]' ]]
assoc_expand_once
bash
いいえ利用可能。または、バックスラッシュを含む一部の値にはorを使用できません[ -v "a[$i]" ]
。そこには引用が必要です。また、見ることができます[[ -v a[$i] ]]
$i
]
$
算術式で連想配列を安全に使用するには?。連想配列の場合でも
bash
(コピー試行とは対照的にksh93
)NULLキーはサポートされbash
ていません。 and を空の文字列としてzsh
使用すると、エラーが発生します。したがって、任意のキー値をテストするには、またはを使用します。[[ -v 'a[$i]' ]]
$i
[[ -n $i && -v 'a[$i]' ]]
[ -n "$i" ] && [ -v 'a[$i]' ]
一般(希少)配列の場合、in
[ -v 'a[expr]' ]
またはは算術[[ -v a[expr] ]]
式expr
として評価されます。これがi
両方とも$i
機能する理由です。算術式は変数を割り当てたり、任意のコマンドを実行する副作用を持つ可能性があるため、使用された$i
値を[ -v 'a[i]' ]
削除することが重要です。そうしないと、ランダムなコマンド実行の脆弱性にさらされます。見たようにbash / POSIXシェルで変数を引用することを忘れてしまうセキュリティリスクbash
、配列のインデックス作成に適用できるという事実[ -v lvalue ]
のために[ -f $file ]
(著者が引用することを忘れて$file
)ACEの脆弱性などの問題が発生しました。[ -n "${var+set}" ]
いずれにせよ、(関連付け)配列要素()に適用されるBourne / POSIXメソッドを常に使用できます。[ -n "${a[$key]+set}" ]
回避策は不要で、すべての配列認識bashバージョン(2.0(1996)以降のバージョン)または連想配列サポートで機能します。 (4.0(2009)以上)、シェル間で移植可能です。これは
[ -v var ]
事実上同じことに注意してください[ -v 'var[0]' ]
。 ksh88と同様に、スカラー変数は配列インデックス0の要素として扱うことができます。配列または関連配列に要素があるか(またはスカラー変数セットがあるかどうか)確認するには、または
[ "${#a[@]}" -gt 0 ]
または[ -v 'a[@]' ]
を実行できます[ -v 'a[*]' ]
。2023年編集、ように@johnraffが指摘、バージョン5.2以降、後者の2つは、5.1互換性が有効になっていない限り、連想配列には適用されません。スパース配列のインデックスまたは関連配列のキーを繰り返すには、次のようにします。
for key in "${!a[@]}"; do printf 'The element of key "%s" is set\n' "$key" done
(
0
スカラー変数が与えられます)
記録するかどうかは次のとおりです。info bash test
またはを実行すると、次info bash '['
の結果が表示されます。バラよりそれに従うBash条件式(内部的に使用される場合[[ ... ]]
)文書は-v
次のとおりです。
-v VARNAME
シェル変数VARNAMEが設定(割り当て)されるとtrueです。
以下help test
がありますが:
-v VAR True if the shell variable VAR is set.
VARNAME
それが何であるか(特に配列メンバーが許可されている場合)、またはVARNAME
参照がスカラー変数ではなく変数に対するものである場合に実行する操作の明示的な仕様はありません。しかし、a[x]
これは通常、変数名が必要なときはいつでも受け入れられ、何十年もやってきたことを考えると、今後もそうすることができると安全に考えることができます。
その公式文書の他の部分を見ると、通常、変数名が予想される場所であればどこにでも(呼出しの有無にかかわらず)暗示することがわかります。名前、VAR、変数名またはより一般的に範囲)、varname[index]
また受け入れられます。たとえば、unset
独自の文書(info bash unset
)、言及されていunset 'array[i]'
ないが配列に関する部分。
これNEWS
ソースディストリビューション(リリースノート)の文書によると、test -v
bash-4.2(2011)に追加されたと示されていますが、おそらく先日(2009年)ksh93t +に追加したksh93にインスピレーションを受けたようです。自己配列要素のサポートはリリースノートに記載されています。 )
F.
test
//「変数」が設定されている場合、成功を返す新しい変数単項演算子[
があります。[[
-v
4.3では:
両方。
test
//[
バイナリ演算子は[[
-v variable
配列参照を理解します。
5.1から:
X。
test -v N
これで、位置パラメータNが設定されているかどうかをテストできます。
CWRU/changelog
ソースコード配布では、連想配列test -v array[@]
または連想配列への参照を見つけることができます。[[ -v array[$key] ]]
これは、この機能が意図的なものであることをもう一度示唆しています。
引用を要求するなど、私が言及した解決策を無効にする可能性がある上記の問題のいくつかを解決するために将来の措置を講じることは不可能ではありません$
。
答え2
Bash 5.2では、連想配列に存在する要素が含まれているかどうかをテストできなくなりtest -v 'arr[@]'
、「@」というキーに対して特別にテストされます。
私はそう思うか、test "${#arr[@]}" -gt 0
そう(( ${#k[@]} > 0 ))
するでしょう。
compat51を参照してください。https://www.gnu.org/software/bash/manual/bash.html#Shell-Compatibility-Mode