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


当前回答

$ myarray=(one two three)
$ case "${myarray[@]}" in  *"two"*) echo "found" ;; esac
found

其他回答

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

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"将不匹配。

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

#!/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

我通常编写这类实用程序来操作变量的名称,而不是变量的值,这主要是因为bash不能通过引用传递变量。

下面是一个使用数组名称的版本:

function array_contains # array value
{
    [[ -n "$1" && -n "$2" ]] || {
        echo "usage: array_contains <array> <value>"
        echo "Returns 0 if array contains value, 1 otherwise"
        return 2
    }

    eval 'local values=("${'$1'[@]}")'

    local element
    for element in "${values[@]}"; do
        [[ "$element" == "$2" ]] && return 0
    done
    return 1
}

这样,问题示例就变成:

array_contains A "one" && echo "contains one"

etc.

a=(b c d)

if printf '%s\0' "${a[@]}" | grep -Fqxz c
then
  echo 'array “a” contains value “c”'
fi

如果你喜欢,你可以使用相同的长选项:

--fixed-strings --quiet --line-regexp --null-data

OP自己添加了以下答案,并附上了评论:

在回答和评论的帮助下,经过一些测试,我得出了这个结论:

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