Jay Taylor's notes

back to listing index

Bash: check if an array contains a value - Stack Overflow

[web search]
Original source (stackoverflow.com)
Tags: stackoverflow.com
Clipped on: 2013-02-08

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.

asked Sep 10 '10 at 15:31
Image (Asset 1/10) alt= 16.9k847107
add comment

10 Answers

up vote 4 down vote accepted

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).

answered Sep 10 '10 at 15:38
Image (Asset 3/10) alt= 18.7k11741
add comment
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
answered Sep 10 '10 at 15:42
Image (Asset 4/10) alt= 629211
1 upvote
 flag
What if an element of the array contains a space? Moreover, would it be possible to make this a function? – Paolo Tedesco Sep 10 '10 at 15:43
  upvote
 flag
Any solution that does not rely on questionable bash hojiggery is preferable. – mkb Sep 10 '10 at 15:44
  upvote
 flag
That said, you can use an indexed for loop and avoid getting killed when an array element contains IFS: for (( i = 0 ; i < ${#array[@]} ; i++ )) – mkb Sep 10 '10 at 15:45
  upvote
 flag
@Paolo: Quoting the array variable in the for statement makes that work. – Dennis Williamson Sep 10 '10 at 15:56
  upvote
 flag
@Matt: You have to be careful using ${#} since Bash supports sparse arrays. – Dennis Williamson Sep 10 '10 at 15:58
add / show 4 more comments

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.

answered Sep 10 '10 at 16:07
Image (Asset 5/10) alt= 65.2k760111
add comment
$ myarray=(one two three)
$ case "${myarray[@]}" in  *"two"*) echo "found" ;; esac
found
answered Sep 11 '10 at 1:35
Image (Asset 6/10) alt= 55.2k54790
  upvote
 flag
nice ! :-) helped me a lot. – Sirex Jul 10 '12 at 21:18
add comment

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.

answered Feb 23 '11 at 3:39
Image (Asset 7/10) alt= 1,095817
add comment

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
  for e in "${@:2}"; do [[ "$e" == "$1" ]] && 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
answered Dec 20 '11 at 11:00
Image (Asset 8/10) alt= 14114
  upvote
 flag
Works nicely! I just have to remember to pass the array as with quotes: "${array[@]}". Otherwise elements containing spaces will break functionality. – Juve Nov 9 '12 at 8:53
add comment
containsElement () { for e in "${@:2}"; do [[ "$e" = "$1" ]] && return 0; done; return 1; }

Now handles empty arrays correctly.

Image (Asset 9/10) alt= 10.4k3938
answered May 3 '12 at 14:46
Image (Asset 10/10) alt= 211