配列要素の単項テスト -v

配列要素の単項テスト -v

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]a2a[2]nullglobfailgloba[2][[ ... ]]

  • 連想配列(テスト済みバージョン5.1以降)の場合、検証するキーが変数にある場合は、最新バージョンで導入されたオプションだけでなく、またはが$i必要です。[ -v 'a[$i]' ][[ -v 'a[$i]' ]]assoc_expand_oncebash いいえ利用可能。または、バックスラッシュを含む一部の値には[ -v "a[$i]" ]orを使用できません[[ -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 -vbash-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] ]]これは、この機能が意図的なものであることをもう一度示唆しています。

引用を要求するなど、私が言及した解決策を無効にする可能性がある上記の問題のいくつかを解決するために将来の措置を講じることは不可能ではありません$

おすすめ記事