在Bash中,测试数组是否包含某个值的最简单方法是什么?
当前回答
$ myarray=(one two three)
$ case "${myarray[@]}" in *"two"*) echo "found" ;; esac
found
其他回答
虽然这里有几个很好的和有用的答案,但我没有找到一个似乎是性能、跨平台和健壮性的正确组合;所以我想分享一下我为我的代码编写的解决方案:
#!/bin/bash
# array_contains "$needle" "${haystack[@]}"
#
# Returns 0 if an item ($1) is contained in an array ($@).
#
# Developer note:
# The use of a delimiter here leaves something to be desired. The ideal
# method seems to be to use `grep` with --line-regexp and --null-data, but
# Mac/BSD grep doesn't support --line-regexp.
function array_contains()
{
# Extract and remove the needle from $@.
local needle="$1"
shift
# Separates strings in the array for matching. Must be extremely-unlikely
# to appear in the input array or the needle.
local delimiter='#!-\8/-!#'
# Create a string with containing every (delimited) element in the array,
# and search it for the needle with grep in fixed-string mode.
if printf "${delimiter}%s${delimiter}" "$@" | \
grep --fixed-strings --quiet "${delimiter}${needle}${delimiter}"; then
return 0
fi
return 1
}
扩展上面来自Sean DiSanti的答案,我认为下面是一个简单而优雅的解决方案,它避免了对数组进行循环,并且不会由于部分匹配而给出假阳性
function is_in_array {
local ELEMENT="${1}"
local DELIM=","
printf "${DELIM}%s${DELIM}" "${@:2}" | grep -q "${DELIM}${ELEMENT}${DELIM}"
}
可以这样称呼:
$ haystack=("needle1" "needle2" "aneedle" "spaced needle")
$ is_in_array "needle" "${haystack[@]}"
$ echo $?
1
$ is_in_array "needle1" "${haystack[@]}"
$ echo $?
0
保持简单:
Array1=( "item1" "item2" "item3" "item-4" )
var="item3"
count=$(echo ${Array1[@]} | tr ' ' '\n' | awk '$1 == "'"$var"'"{print $0}' | wc -l)
[ $count -eq 0 ] && echo "Not found" || echo "found"
以下是我对这个问题的看法。以下是简短的版本:
function arrayContains() {
local haystack=${!1}
local needle="$2"
printf "%s\n" ${haystack[@]} | grep -q "^$needle$"
}
长一点的版本,我觉得看起来更舒服。
# With added utility function.
function arrayToLines() {
local array=${!1}
printf "%s\n" ${array[@]}
}
function arrayContains() {
local haystack=${!1}
local needle="$2"
arrayToLines haystack[@] | grep -q "^$needle$"
}
例子:
test_arr=("hello" "world")
arrayContains test_arr[@] hello; # True
arrayContains test_arr[@] world; # True
arrayContains test_arr[@] "hello world"; # False
arrayContains test_arr[@] "hell"; # False
arrayContains test_arr[@] ""; # False
@ghostdog74关于使用大小写逻辑检查数组包含特定值的回答的一个小补充:
myarray=(one two three)
word=two
case "${myarray[@]}" in ("$word "*|*" $word "*|*" $word") echo "found" ;; esac
或者打开extglob选项,你可以这样做:
myarray=(one two three)
word=two
shopt -s extglob
case "${myarray[@]}" in ?(*" ")"$word"?(" "*)) echo "found" ;; esac
我们也可以用if语句:
myarray=(one two three)
word=two
if [[ $(printf "_[%s]_" "${myarray[@]}") =~ .*_\[$word\]_.* ]]; then echo "found"; fi