检查 Bash 数组是否包含值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3685970/
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
Check if a Bash array contains a value
提问by Paolo Tedesco
In Bash, what is the simplest way to test if an array contains a certain value?
在 Bash 中,测试数组是否包含某个值的最简单方法是什么?
Edit: With help from the answers and the comments, after some testing, I came up with this:
编辑:在答案和评论的帮助下,经过一些测试,我想出了这个:
function contains() {
local n=$#
local value=${!n}
for ((i=1;i < $#;i++)) {
if [ "${!i}" == "${value}" ]; then
echo "y"
return 0
fi
}
echo "n"
return 1
}
A=("one" "two" "three four")
if [ $(contains "${A[@]}" "one") == "y" ]; then
echo "contains one"
fi
if [ $(contains "${A[@]}" "three") == "y" ]; then
echo "contains three"
fi
I'm not sure if it's the best solution, but it seems to work.
我不确定这是否是最好的解决方案,但它似乎有效。
回答by Keegan
This approach has the advantage of not needing to loop over all the elements (at least not explicitly). But since array_to_string_internal()
in array.cstill loops over array elements and concatenates them into a string, it's probably not more efficient than the looping solutions proposed, but it's more readable.
这种方法的优点是不需要遍历所有元素(至少不是明确地)。但是由于array_to_string_internal()
在array.c 中仍然循环遍历数组元素并将它们连接成一个字符串,它可能不会比提出的循环解决方案更有效,但它更具可读性。
if [[ " ${array[@]} " =~ " ${value} " ]]; then
# whatever you want to do when array contains value
fi
if [[ ! " ${array[@]} " =~ " ${value} " ]]; then
# whatever you want to do when array doesn't contain value
fi
Note that in cases where the value you are searching for is one of the words in an array element with spaces, it will give false positives. For example
请注意,如果您要搜索的值是带有空格的数组元素中的单词之一,则会产生误报。例如
array=("Hyman Brown")
value="Hyman"
The regex will see "Hyman" as being in the array even though it isn't. So you'll have to change IFS
and the separator characters on your regex if you want still to use this solution, like this
正则表达式会看到“Hyman”在数组中,即使它不是。因此,IFS
如果您仍想使用此解决方案,则必须更改正则表达式中的分隔符,如下所示
IFS=$'\t'
array=("Hyman Brown\tHyman Smith")
unset IFS
value="Hyman"
if [[ "\t${array[@]}\t" =~ "\t${value}\t" ]]; then
echo "true"
else
echo "false"
fi
This will print "false".
这将打印“假”。
Obviously this can also be used as a test statement, allowing it to be expressed as a one-liner
显然这也可以用作测试语句,允许它表示为单行
[[ " ${array[@]} " =~ " ${value} " ]] && echo "true" || echo "false"
回答by patrik
Below is a small function for achieving this. The search string is the first argument and the rest are the array elements:
下面是实现此目的的一个小函数。搜索字符串是第一个参数,其余是数组元素:
containsElement () {
local e match=""
shift
for e; do [[ "$e" == "$match" ]] && return 0; done
return 1
}
A test run of that function could look like:
该函数的测试运行可能如下所示:
$ array=("something to search for" "a string" "test2000")
$ containsElement "a string" "${array[@]}"
$ echo $?
0
$ containsElement "blaha" "${array[@]}"
$?echo $?
1
回答by ghostdog74
$ myarray=(one two three)
$ case "${myarray[@]}" in *"two"*) echo "found" ;; esac
found
回答by Scott
for i in "${array[@]}"
do
if [ "$i" -eq "$yourValue" ] ; then
echo "Found"
fi
done
For strings:
对于字符串:
for i in "${array[@]}"
do
if [ "$i" == "$yourValue" ] ; then
echo "Found"
fi
done
回答by JellicleCat
One-line solution
一站式解决方案
printf '%s\n' ${myarray[@]} | grep -P '^mypattern$'
Explanation
解释
The printf
statement prints each element of the array on a separate line.
该printf
语句在单独的行上打印数组的每个元素。
The grep
statement uses the special characters ^
and $
to find a line that contains exactlythe pattern given as mypattern
(no more, no less).
该grep
语句使用特殊字符^
并$
查找包含完全给定模式的行mypattern
(不多也不少)。
Usage
用法
To put this into an if ... then
statement:
将其放入if ... then
声明中:
if printf '%s\n' ${myarray[@]} | grep -q -P '^mypattern$'; then
# ...
fi
I added a -q
flag to the grep
expression so that it won't print matches; it will just treat the existence of a match as "true."
我-q
在grep
表达式中添加了一个标志,这样它就不会打印匹配项;它只会将匹配的存在视为“真实”。
回答by LeoRochael
If you need performance, you don't want to loop over your whole array every time you search.
如果您需要性能,您不希望每次搜索时都遍历整个数组。
In this case, you can create an associative array (hash table, or dictionary) that represents an index of that array. I.e. it maps each array element into its index in the array:
在这种情况下,您可以创建一个关联数组(哈希表或字典)来表示该数组的索引。即它将每个数组元素映射到它在数组中的索引:
make_index () {
local index_name=
shift
local -a value_array=("$@")
local i
# -A means associative array, -g means create a global variable:
declare -g -A ${index_name}
for i in "${!value_array[@]}"; do
eval ${index_name}["${value_array[$i]}"]=$i
done
}
Then you can use it like this:
然后你可以像这样使用它:
myarray=('a a' 'b b' 'c c')
make_index myarray_index "${myarray[@]}"
And test membership like so:
并像这样测试会员资格:
member="b b"
# the "|| echo NOT FOUND" below is needed if you're using "set -e"
test "${myarray_index[$member]}" && echo FOUND || echo NOT FOUND
Or also:
或者也:
if [ "${myarray_index[$member]}" ]; then
echo FOUND
fi
Notice that this solution does the right thing even if the there are spaces in the tested value or in the array values.
请注意,即使测试值或数组值中有空格,此解决方案也会做正确的事情。
As a bonus, you also get the index of the value within the array with:
作为奖励,您还可以通过以下方式获得数组中值的索引:
echo "<< ${myarray_index[$member]} >> is the index of $member"
回答by Sean DiSanti
I typically just use:
我通常只使用:
inarray=$(echo ${haystack[@]} | grep -o "needle" | wc -w)
non zero value indicates a match was found.
非零值表示找到匹配项。
回答by estani
Another one liner without a function:
另一个没有功能的班轮:
(for e in "${array[@]}"; do [[ "$e" == "searched_item" ]] && exit 0; done) && echo "found" || echo "not found"
Thanks @Qwerty for the heads up regarding spaces!
感谢@Qwerty 提供有关空间的提示!
corresponding function:
对应功能:
find_in_array() {
local word=
shift
for e in "$@"; do [[ "$e" == "$word" ]] && return 0; done
return 1
}
example:
例子:
some_words=( these are some words )
find_in_array word "${some_words[@]}" || echo "expected missing! since words != word"
回答by Yann
containsElement () { for e in "${@:2}"; do [[ "$e" = "" ]] && return 0; done; return 1; }
Nowhandles empty arrays correctly.
现在可以正确处理空数组。
回答by hornetbzz
Here is a small contribution :
这是一个小贡献:
array=(word "two words" words)
search_string="two"
match=$(echo "${array[@]:0}" | grep -o $search_string)
[[ ! -z $match ]] && echo "found !"
Note: this way doesn't distinguish the case "two words" but this is not required in the question.
注意:这种方式不区分大小写“两个词”,但这在问题中不是必需的。