17

文字列が文字列の配列に存在するかどうかを確認する方法はありますか?配列を反復せずに?

たとえば、次のスクリプトが与えられた場合、変数 $test に格納された値が $array に存在するかどうかをテストするために正しく実装するにはどうすればよいでしょうか?

array=('hello' 'world' 'my' 'name' 'is' 'perseus')

#pseudo code
$test='henry'
if [$array[$test]]
   then
      do something
   else
      something else
fi

ノート

私はbash 4.1.5を使用しています

4

10 に答える 10

15

bash 4 でできる最も近いのは、連想配列を使用することです。

declare -A map
for name in hello world my name is perseus; do
  map["$name"]=1
done

...次とまったく同じことを行います:

declare -A map=( [hello]=1 [my]=1 [name]=1 [is]=1 [perseus]=1 )

...に続く:

tgt=henry
if [[ ${map["$tgt"]} ]] ; then
  : found
fi
于 2012-07-09T14:18:06.830 に答える
9

技術的には常に反復がありますが、シェルの基礎となる配列コードに追いやられる可能性があります。シェル拡張は、実装の詳細を隠す抽象化を提供し、シェル スクリプト内での明示的なループの必要性を回避します。

この使用例の単語境界の処理は、単語全体の固定文字列を処理する組み込み機能を備えたfgrepを使用すると簡単です。正規表現の一致を正しく行うのは困難ですが、以下の例は提供されたコーパスで機能します。

外部 grep プロセス

array=('hello' 'world' 'my' 'name' 'is' 'perseus')
word="world"
if echo "${array[@]}" | fgrep --word-regexp "$word"; then
    : # do something
fi

Bash 正規表現テスト

array=('hello' 'world' 'my' 'name' 'is' 'perseus')
word="world"
if [[ "${array[*]}" =~ (^|[^[:alpha:]])$word([^[:alpha:]]|$) ]]; then
    : # do something
fi
于 2012-07-09T14:24:13.143 に答える
4

Bash 4 を使用しているため、連想配列を使用できます。

declare -A array=([hello]= [world]= [my]= [name]= [is]= [perseus]=)

test='henry'
if [[ ${array[$test]-X} == ${array[$test]} ]]
then
    do something
else
    something else
fi

配列要素が設定されていない場合、パラメーター展開は "X" に置き換えられます (ただし、null の場合は設定されません)。それを行い、結果が元の値と異なるかどうかを確認することで、その値に関係なくキーが存在するかどうかがわかります。

于 2012-07-09T14:18:28.383 に答える
2
array=('hello' 'world' 'my' 'name' 'is' 'perseus')
regex="^($(IFS=\|; echo "${array[*]}"))$"

test='henry'
[[ $test =~ $regex ]] && echo "found" || echo "not found"
于 2014-03-26T10:29:15.680 に答える
1

あなたの投稿を読んで、文字列が配列に存在するかどうかを知りたいだけでなく(タイトルが示唆するように)、その文字列が実際にその配列の要素に対応しているかどうかを知りたいと思います。その場合は読み進めてください。

うまくいきそうな方法を見つけました。

私のように bash 3.2 をスタックしている場合に便利です (ただし、bash 4.2 でテストされ、動作しています):

array=('hello' 'world' 'my' 'name' 'is' 'perseus')
IFS=:     # We set IFS to a character we are confident our 
          # elements won't contain (colon in this case)

test=:henry:        # We wrap the pattern in the same character

# Then we test it:
# Note the array in the test is double quoted, * is used (@ is not good here) AND 
# it's wrapped in the boundary character I set IFS to earlier:
[[ ":${array[*]}:" =~ $test ]] && echo "found! :)" || echo "not found :("
not found :(               # Great! this is the expected result

test=:perseus:      # We do the same for an element that exists
[[ ":${array[*]}:" =~ $test ]] && echo "found! :)" || echo "not found :("
found! :)               # Great! this is the expected result

array[5]="perseus smith"    # For another test we change the element to an 
                            # element with spaces, containing the original pattern.

test=:perseus:
[[ ":${array[*]}:" =~ $test ]] && echo "found!" || echo "not found :("
not found :(               # Great! this is the expected result

unset IFS        # Remember to unset IFS to revert it to its default value  

これを説明しましょう:

"${array[*]}"この回避策は、 (二重引用符とアスタリスクに注意してください) IFS の最初の文字で区切られた配列の要素のリストに展開されるという原則に基づいています。

  1. したがって、IFS を境界として使用したいもの (私の場合はコロン) に設定する必要があります。

    IFS=:
    
  2. 次に、探している要素を同じ文字でラップします。

    test=:henry:
    
  3. そして最後に、配列でそれを探します。テストを行うために従ったルールに注意してください (すべて必須です): 配列は二重引用符で囲まれ、* が使用され (@ は適切ではありません)、IFS を以前に設定した境界文字でラップされています:

    [[ ":${array[*]}:" =~ $test ]] && echo found || echo "not found :("
    not found :(
    
  4. 存在する要素を探す場合:

    test=:perseus:
    [[ ":${array[*]}:" =~ $test ]] && echo "found! :)" || echo "not found :("
    found! :)
    
  5. 別のテストでは、最後の要素 'perseus' を 'perseus smith' (スペースを含む要素) に変更して、一致するかどうかを確認することができます (一致しないはずです):

    array[5]="perseus smith"
    test=:perseus:
    [[ ":${array[*]}:" =~ $test ]] && echo "found!" || echo "not found :("
    not found :(
    

    「perseus」自体はもはや要素ではないため、これは予想される結果です。

  6. 重要: テストが完了したら、忘れずに IFS の設定を解除して、デフォルト値 (未設定) に戻してください。

    unset IFS
    

これまでのところ、この方法は機能しているようです。注意して、要素に含まれていないことが確実な IFS の文字を選択する必要があります。

誰にも役立つことを願っています!

よろしく、 フレッド

于 2015-04-29T10:42:08.227 に答える
0
q=( 1 2 3 )
[ "${q[*]/1/}" = "${q[*]}" ] && echo not in array || echo in array 
#in array
[ "${q[*]/7/}" = "${q[*]}" ] && echo not in array || echo in array 
#not in array
于 2014-06-28T07:46:53.140 に答える