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


当前回答

下面的代码检查给定值是否在数组中,并返回其从零开始的偏移量:

A=("one" "two" "three four")
VALUE="two"

if [[ "$(declare -p A)" =~ '['([0-9]+)']="'$VALUE'"' ]];then
  echo "Found $VALUE at offset ${BASH_REMATCH[1]}"
else
  echo "Couldn't find $VALUE"
fi

匹配是在完整的值上完成的,因此设置VALUE="three"将不匹配。

其他回答

我通常只使用:

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

非零值表示找到了匹配。

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

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

另一个没有函数的代码:

(for e in "${array[@]}"; do [[ "$e" == "searched_item" ]] && exit 0; done) && echo "found" || echo "not found"

谢谢@Qwerty关于空格的提示!

对应的功能:

find_in_array() {
  local word=$1
  shift
  for e in "$@"; do [[ "$e" == "$word" ]] && return 0; done
  return 1
}

例子:

some_words=( these are some words )
find_in_array word "${some_words[@]}" || echo "expected missing! since words != word"

有点晚了,但你可以用这个:

#!/bin/bash
# isPicture.sh

FILE=$1
FNAME=$(basename "$FILE") # Filename, without directory
EXT="${FNAME##*.}" # Extension

FORMATS=(jpeg JPEG jpg JPG png PNG gif GIF svg SVG tiff TIFF)

NOEXT=( ${FORMATS[@]/$EXT} ) # Formats without the extension of the input file

# If it is a valid extension, then it should be removed from ${NOEXT},
#+making the lengths inequal.
if ! [ ${#NOEXT[@]} != ${#FORMATS[@]} ]; then
    echo "The extension '"$EXT"' is not a valid image extension."
    exit
fi

结合Beorn Harris和loentar的回答,我们得出了一个更有趣的单行测试:

delim=$'\x1F' # define a control code to be used as more or less reliable delimiter
if [[ "${delim}${array[@]}${delim}" =~ "${delim}a string to test${delim}" ]]; then
    echo "contains 'a string to test'"
fi

它不使用额外的函数,不替换测试,并添加了额外的保护,防止使用控制代码作为分隔符偶尔出现错误匹配。


UPD:感谢@ChrisCogdon的注意,这个错误的代码被重写并以https://stackoverflow.com/a/58527681/972463的形式发布。

使用参数展开:

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

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