在Bash中,测试数组是否包含某个值的最简单方法是什么?


当前回答

我通常只使用:

inarray=$(echo ${haystack[@]} | grep -o "needle" | wc -w)

非零值表示找到了匹配。

... 实际上,为了解决它不能与needle1和needle2工作的问题,如果你只想要一个精确匹配,没有更多,没有更少,只需在-o后面添加一个w标志,用于整个单词匹配:

inarray=$(echo ${haystack[@]} | grep -ow "needle" | wc -w)

其他回答

考虑到:

array=("something to search for" "a string" "test2000")
elem="a string"

然后简单检查一下:

if c=$'\x1E' && p="${c}${elem} ${c}" && [[ ! "${array[@]/#/${c}} ${c}" =~ $p ]]; then
  echo "$elem exists in array"
fi

在哪里

c is element separator
p is regex pattern

(单独分配p,而不是直接在[[]]中使用表达式的原因是为了保持bash 4的兼容性)

这种方法的优点是不需要遍历所有元素(至少不是显式地)。但是由于array.c中的array_to_string_internal()仍然循环遍历数组元素并将它们连接到一个字符串中,因此它可能并不比所提出的循环解决方案更有效,但它更具可读性。

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

请注意,如果您正在搜索的值是带有空格的数组元素中的某个单词,则会给出假阳性。例如

array=("Jack Brown")
value="Jack"

正则表达式将“Jack”视为在数组中,即使它不在数组中。所以你必须改变IFS和正则表达式上的分隔符如果你仍然想使用这个解决方案,就像这样

IFS="|"
array=("Jack Brown${IFS}Jack Smith")
value="Jack"

if [[ "${IFS}${array[*]}${IFS}" =~ "${IFS}${value}${IFS}" ]]; then
    echo "true"
else
    echo "false"
fi

unset IFS # or set back to original IFS if previously set

这将打印“false”。

显然,这也可以用作测试语句,允许将其表示为一行程序

[[ " ${array[*]} " =~ " ${value} " ]] && echo "true" || echo "false"

这是一个小小的贡献:

array=(word "two words" words)  
search_string="two"  
match=$(echo "${array[@]:0}" | grep -o $search_string)  
[[ ! -z $match ]] && echo "found !"  

注意:这种方法不区分大小写“两个单词”,但在问题中不需要这样做。

使用参数展开:

如果参数为空或未设置,则什么都没有 替换,否则词的展开就会被替换。

declare -A myarray
myarray[hello]="world"

for i in hello goodbye 123
do
  if [ ${myarray[$i]:+_} ]
  then
    echo ${!myarray[$i]} ${myarray[$i]} 
  else
    printf "there is no %s\n" $i
  fi
done

保持简单:

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"