Check if a Bash array contains a value

0 votes
asked Sep 10, 2010 by paolo-tedesco

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

Edit: 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

I'm not sure if it's the best solution, but it seems to work.

30 Answers

0 votes
answered Jan 10, 2010 by scott
for i in "${array[@]}"
do
    if [ "$i" -eq "$yourValue" ] ; then
        echo "Found"
    fi
done

For strings:

for i in "${array[@]}"
do
    if [ "$i" == "$yourValue" ] ; then
        echo "Found"
    fi
done
0 votes
answered Jan 10, 2010 by dennis-williamson

If you want to do a quick and dirty test to see if it's worth iterating over the whole array to get a precise match, Bash can treat arrays like scalars. Test for a match in the scalar, if none then skipping the loop saves time. Obviously you can get false positives.

array=(word "two words" words)
if [[ ${array[@]} =~ words ]]
then
    echo "Checking"
    for element in "${array[@]}"
    do
        if [[ $element == "words" ]]
        then
            echo "Match"
        fi
    done
fi

This will output "Checking" and "Match". With array=(word "two words" something) it will only output "Checking". With array=(word "two widgets" something) there will be no output.

0 votes
answered Jan 11, 2010 by ghostdog74
$ myarray=(one two three)
$ case "${myarray[@]}" in  *"two"*) echo "found" ;; esac
found
0 votes
answered Sep 10, 2010 by bta

There is sample code that shows how to replace a substring from an array. You can make a copy of the array and try to remove the target value from the copy. If the copy and original are then different, then the target value exists in the original string.

The straightforward (but potentially more time-consuming) solution is to simply iterate through the entire array and check each item individually. This is what I typically do because it is easy to implement and you can wrap it in a function (see this info on passing an array to a function).

0 votes
answered Jan 23, 2011 by hornetbzz

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 votes
answered Sep 20, 2011 by patrik

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 votes
answered Jan 3, 2012 by yann
containsElement () { for e in "${@:2}"; do [[ "$e" = "$1" ]] && return 0; done; return 1; }

Now handles empty arrays correctly.

0 votes
answered Jan 17, 2012 by estani

Another one liner without a function:

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

Thanks @Qwerty for the heads up regarding spaces!

0 votes
answered Jan 1, 2013 by sigg3-net

This could be worth investigating if you don't want to iterate:

#!/bin/bash
myarray=("one" "two" "three");
wanted="two"
if `echo ${myarray[@]/"$wanted"/"WAS_FOUND"} | grep -q "WAS_FOUND" ` ; then
 echo "Value was found"
fi
exit

Snippet adapted from: http://www.thegeekstuff.com/2010/06/bash-array-tutorial/ I think it is pretty clever.

EDIT: You could probably just do:

if `echo ${myarray[@]} | grep -q "$wanted"` ; then
echo "Value was found"
fi

But the latter only works if the array contains unique values. Looking for 1 in "143" will give false positive, methinks.

0 votes
answered Jan 9, 2013 by sven-rieke

The following code checks if a given value is in the array and returns its zero-based offset:

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

The match is done on the complete values, therefore setting VALUE="three" would not match.

Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...