检查元素是否存在于 Bash 数组中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14366390/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 23:13:23  来源:igfitidea点击:

Check if an element is present in a Bash array

arraysbashshellsearch

提问by QuantumLicht

I was wondering if there is an efficient way to check if an element is present within an array in Bash? I am looking for something similar to what I can do in Python, like:

我想知道是否有一种有效的方法来检查 Bash 中的数组中是否存在元素?我正在寻找类似于我在 Python 中可以做的事情,例如:

arr = ['a','b','c','d']

if 'd' in arr:
    do your thing
else:
    do something

I've seen solutions using associative array for bash for Bash 4+, but I am wondering if there is another solution out there.

我已经看到针对 Bash 4+ 的 bash 使用关联数组的解决方案,但我想知道是否还有其他解决方案。

Please understand that I know the trivial solution is to iterate in the array, but I don't want that.

请理解,我知道简单的解决方案是在数组中迭代,但我不想要那样。

回答by glenn Hymanman

You could do:

你可以这样做:

if [[ " ${arr[*]} " == *" d "* ]]; then
    echo "arr contains d"
fi

This will give false positives for example if you look for "a b" -- that substring is in the joined string but not as an array element. This dilemma will occur for whatever delimiter you choose.

例如,如果您查找“a b”,这将产生误报——该子字符串在连接字符串中,但不是作为数组元素。无论您选择什么分隔符,都会出现这种困境。

The safest way is to loop over the array until you find the element:

最安全的方法是遍历数组直到找到元素:

array_contains () {
    local seeking=; shift
    local in=1
    for element; do
        if [[ $element == "$seeking" ]]; then
            in=0
            break
        fi
    done
    return $in
}

arr=(a b c "d e" f g)
array_contains "a b" "${arr[@]}" && echo yes || echo no    # no
array_contains "d e" "${arr[@]}" && echo yes || echo no    # yes

Here's a "cleaner" version where you just pass the array name, not all its elements

这是一个“更干净”的版本,您只需传递数组名称,而不是它的所有元素

array_contains2 () { 
    local array="[@]"
    local seeking=
    local in=1
    for element in "${!array}"; do
        if [[ $element == "$seeking" ]]; then
            in=0
            break
        fi
    done
    return $in
}

array_contains2 arr "a b"  && echo yes || echo no    # no
array_contains2 arr "d e"  && echo yes || echo no    # yes


For associative arrays, there's a very tidy way to test if the array contains a given key: The -voperator

对于关联数组,有一种非常简洁的方法来测试数组是否包含给定的-v运算符

$ declare -A arr=( [foo]=bar [baz]=qux )
$ [[ -v arr[foo] ]] && echo yes || echo no
yes
$ [[ -v arr[bar] ]] && echo yes || echo no
no

See 6.4 Bash Conditional Expressionsin the manual.

请参阅手册中的6.4 Bash 条件表达式

回答by Steven Penny

Obvious caveats aside, if your array was actually like the one above, you could do

除了明显的警告之外,如果您的阵列实际上与上面的一样,您可以这样做

if [[ ${arr[*]} =~ d ]]
then
  do your thing
else
  do something
fi

回答by Marcin Wasiluk

1) Initialize array arrand add elements

1) 初始化数组arr并添加元素

2) set variable to search for SEARCH_STRING

2) 设置要搜索的变量 SEARCH_STRING

3) check if your array contains element

3)检查你的数组是否包含元素

arr=()
arr+=('a')
arr+=('b')
arr+=('c')

SEARCH_STRING='b'

if [[ " ${arr[*]} " == *"$SEARCH_STRING"* ]];
then
    echo "YES, your arr contains $SEARCH_STRING"
else
    echo "NO, your arr does not contain $SEARCH_STRING"
fi

回答by jesjimher

If array elements don't contain spaces, another (perhaps more readable) solution would be:

如果数组元素不包含空格,另一个(可能更易读)的解决方案是:

if echo ${arr[@]} | grep -q -w "d"; then 
    echo "is in array"
else 
    echo "is not in array"
fi

回答by Qwerty

array=("word" "two words") # let's look for "two words"

using grepand printf:

使用grepprintf

(printf '%s\n' "${array[@]}" | grep -x -q "two words") && <run_your_if_found_command_here>

using for:

使用for

(for e in "${array[@]}"; do [[ "$e" == "two words" ]] && exit 0; done; exit 1) && <run_your_if_found_command_here>

For not_found results add || <run_your_if_notfound_command_here>

对于 not_found 结果添加 || <run_your_if_notfound_command_here>

回答by ssc

As bash does not have a built-in valueinarrayoperator and the =~operator or the [[ "${array[@]" == *"${item}"* ]]notation keep confusing me, I usually combine grepwith a here-string:

由于 bash 没有内置in数组运算符,并且=~运算符或[[ "${array[@]" == *"${item}"* ]]符号让我感到困惑,因此我通常grep与 here-string结合使用:

colors=('black' 'blue' 'light green')
if grep -q 'black' <<< "${colors[@]}"
then
    echo 'match'
fi

Bewarehowever that this suffers from the same false positives issue as many of the other answers that occurs when the item to search for is fully contained, but is not equal to another item:

但是请注意,当要搜索的项目完全包含但不等于另一个项目时,会遇到与许多其他答案相同的误报问题:

if grep -q 'green' <<< "${colors[@]}"
then
    echo 'should not match, but does'
fi

If that is an issue for your use case, you probably won't get around looping over the array:

如果这对您的用例来说是一个问题,您可能不会绕过数组:

for color in "${colors[@]}"
do
    if [ "${color}" = 'green' ]
    then
        echo "should not match and won't"
        break
    fi
done

for color in "${colors[@]}"
do
    if [ "${color}" = 'light green' ]
    then
        echo 'match'
        break
    fi
done

回答by Jasonovich

Here's another way that might be faster, in terms of compute time, than iterating. Not sure. The idea is to convert the array to a string, truncate it, and get the size of the new array.

这是另一种在计算时间方面可能比迭代更快的方法。没有把握。这个想法是将数组转换为字符串,截断它,并获得新数组的大小。

For example, to find the index of 'd':

例如,要查找 'd' 的索引:

arr=(a b c d)    
temp=`echo ${arr[@]}`
temp=( ${temp%%d*} )
index=${#temp[@]}

You could turn this into a function like:

你可以把它变成一个函数,比如:

get-index() {

    Item=
    Array="[@]"

    ArgArray=( ${!Array} )
    NewArray=( ${!Array%%${Item}*} )

    Index=${#NewArray[@]}

    [[ ${#ArgArray[@]} == ${#NewArray[@]} ]] && echo -1 || echo $Index

}

You could then call:

然后你可以调用:

get-index d arr

and it would echo back 3, which would be assignable with:

它会回显 3,它可以分配给:

index=`get-index d arr`

回答by Edward Falk

FWIW, here's what I used:

FWIW,这是我使用的:

expr "${arr[*]}" : ".*\<$item\>"

This works where there are no delimiters in any of the array items or in the search target. I didn't need to solve the general case for my applicaiton.

这适用于任何数组项或搜索目标中没有分隔符的情况。我不需要解决我的应用程序的一般情况。