Check if a Bash array contains a value

前端 未结 30 2407
执笔经年
执笔经年 2020-11-22 07:14

In Bash, what is the simplest way to test if an array contains a certain value?

相关标签:
30条回答
  • 2020-11-22 07:46

    The OP added the following answer themselves, with the commentary:

    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
    
    0 讨论(0)
  • 2020-11-22 07:47

    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="$1"
      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
    
    0 讨论(0)
  • 2020-11-22 07:48

    Using grep and printf

    Format each array member on a new line, then grep the lines.

    if printf '%s\n' "${array[@]}" | grep -x -q "search string"; then echo true; else echo false; fi
    
    example:
    $ array=("word", "two words")
    $ if printf '%s\n' "${array[@]}" | grep -x -q "two words"; then echo true; else echo false; fi
    true
    

    Note that this has no problems with delimeters and spaces.

    0 讨论(0)
  • 2020-11-22 07:50

    One-line check without 'grep' and loops

    if ( dlm=$'\x1F' ; IFS="$dlm" ; [[ "$dlm${array[*]}$dlm" == *"$dlm${item}$dlm"* ]] ) ; then
      echo "array contains '$item'"
    else
      echo "array does not contain '$item'"
    fi
    

    This approach uses neither external utilities like grep nor loops.

    What happens here, is:

    • we use a wildcard substring matcher to find our item in the array that is concatenated into a string;
    • we cut off possible false positives by enclosing our search item between a pair of delimiters;
    • we use a non-printable character as delimiter, to be on the safe side;
    • we achieve our delimiter being used for array concatenation too by temporary replacement of the IFS variable value;
    • we make this IFS value replacement temporary by evaluating our conditional expression in a sub-shell (inside a pair of parentheses)
    0 讨论(0)
  • 2020-11-22 07:50

    I generally write these kind of utilities to operate on the name of the variable, rather than the variable value, primarily because bash can't otherwise pass variables by reference.

    Here's a version that works with the name of the array:

    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
    }
    

    With this, the question example becomes:

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

    etc.

    0 讨论(0)
  • 2020-11-22 07:51

    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.

    0 讨论(0)
提交回复
热议问题