1. Introduction
There are a couple of instances where it might be necessary to check if a Bash array contains a certain value. For example, if we’re trying to confirm that the Bash array we’re using in log alerting contains a certain log path, we’d have to search the log path array.
In this tutorial, we’ll discuss different methods for checking if a Bash array contains a value. We’ll use the for loop, grep, if conditions, and many other options.
2. Using an if Condition With a regex Pattern
We can check if a Bash array contains a value by using an if condition*.* To do this, we’ll create a condition that checks if a string of all elements in the array matches a regex pattern of our value.
Let’s create a script file named search.sh:
$ cat search.sh
#! /bin/bash
array=("one" "two" "potatoes" "bananas" "three" "apples")
value="\<${1}\>" #the value variable is assigned a regex that matches the exact value of the first argument
if [[ ${array[@]} =~ $value ]]
then
echo "value found"
else
echo "value not found"
fi
After creating the script, we’ll run it to confirm it works:
$ ./search.sh bananas
value found
The stdout confirms that the array contains the value “bananas”.
Here, the stdout shows there’s no “banana“ in our array:
$ ./search.sh banana
value not found
While the if condition method doesn’t do a Bash loop over the elements of the array, there’s still some looping going on. The ${array[@]} expression is based on a C function that loops over every element in the array. This could be important when working with arrays of larger sizes.
3. Using an if Condition With fgrep
In place of the regular regex pattern we used in the previous section, we can write our if condition with fgrep.
To see how this works, we’ll create a script, search_if_with_fgrep.sh:
$ cat search_if_with_fgrep.sh
#! /bin/bash
array=("one" "two" "potatoes" "bananas" "three" "apples")
value=$1
if [[ $(echo ${array[@]} | fgrep -w $value) ]]
then
echo "value found"
else
echo "value not found"
fi
Let’s see if the script works:
$ ./search_if_with_grep.sh apples
value found
Here, our if condition evaluates to true because “apples” is in the array.
Next, since “apple” is not a part of the array, our output shows “value not found“:
$ ./search_if_with_grep.sh apple
value not found
We can use grep in place of fgrep. However, in this case, we opted for fgrep because it offers better performance when searching for fixed strings.
4. Using a for Loop and an if Condition
We can also use a for loop with a nested if condition to search for a specific value in an array. However, depending on what we want, we can do this in two ways:
- We can loop through the elements of the array, then check if the elements match our value using an if condition*.*
- We can loop through every value separated by whitespace in the array, then check if any of those values matches our value using an if condition*.*
4.1. Matching the Value to Elements of the Array
This option is perfect for when trying to check if our value exists in the array as a whole element. Here, the value is compared with elements of the array, not substrings of the elements of the array.
First, we’ll write a script, search_for_if.sh:
$ cat search_for_if.sh
#! /bin/bash
array=("one" "two" "potatoes" "bananas" "three" "apples")
for i in "${array[@]}"
do
if [[ $i == $1 ]]
then
echo "value found" && exit 0
fi
done
Next, we’ll test it with “potatoes” as our argument:
$ ./search_for_if.sh potatoes
value found
The stdout prints “value found” to confirm that “potatoes” is in the array.
If our value isn’t in the array, nothing will be printed on stdout:
$ ./search_for_if.sh potato
4.2. Matching the Value to the Array Values Separated by Whitespace
This option is best when we’re trying to match our value to subsets of the elements of the array separated by whitespaces.
To see how it works, we’ll write a script file called search_for_if_whitespaces.sh:
$ cat search_for_if_whitespaces.sh
#! /bin/bash
array=("one two" "potatoes potato" "banana bananas" "three" "apples")
for i in ${array[@]}
do
if [[ $i == $1 ]]
then
echo "value found" && exit 0
fi
done
Most of the code for this approach is similar to the previous one. However, instead of interpolating the array with “${array[@]}”, we use** ${array[@]}. We simply remove the quotation marks around the command that prints all elements of the array.
When we use “${array[@]}” in the for loop, i is assigned the value of an element of the array during each iteration. But *with ${array[@]}, i is assigned a single value*. That value is a string of the whole array with its elements separated by whitespaces.
With this new script, this is our result when we try to match “one“:
$ ./search_for_if_whitespaces.sh one
value found
Then when we try to match “two“, we get the same result:
$ ./search_for_if_whitespaces.sh two
value found
But when we try to match “one two“, we get no result:
$ ./search_for_if_whitespaces.sh "one two"
5. Using printf and grep in an if Condition
In this method, we’ll print all the elements of the array with a null delimiter using printf. Next, we’ll grep our value from the output of the printf command. Finally, we’ll test the exit status of the printf and grep commands using an if condition.
Let’s put this into practice. Let’s create a script named search_if_printf_grep.sh:
$ cat search_if_printf_grep.sh
#! /bin/bash
array=("one" "two" "potatoes" "bananas" "three" "apples")
value=$1
if printf '%s\0' "${array[@]}" | grep -qwz $value
then
echo "value found"
else
echo "value not found"
fi
Testing the script with “apples” as the argument displays “value found” because “apples” is in the array:
$ ./search_if_printf_grep.sh apples
value found
But when we test it with “apple” as our argument, the stdout prints “value not found” because “apple” isn’t in the array:
$ ./search_if_printf_grep.sh apple
value not found
5.1. Understanding the printf and grep Command
The printf ‘%s\0’ “${array[@]}” | grep -qwz $value consists of two parts: the printf part and the grep part.
In the printf part, the %s format character tells printf to treat its arguments (the elements of the array) as a string. Then the \0 tells printf to use a null byte delimiter between the elements of the array. We used null byte instead of newline because of the possibility of an array element being a newline character.
In the grep part, we used two pattern selection options (-wz) and one output control option (-q). Option -q suppresses normal output. Without it, stdout displays our value along with “value found” if our value is in the array.
With -w in the command, grep only matches the whole value string. It won’t match its individual characters. This way, we won’t get false positives.
Adding -z tells grep that each data line ends in null byte, not newline.
6. Conclusion
In this article, we saw five ways of checking if a Bash array contains a value. To pull off some of them, we used conditionals alongside grep, fgrep, and printf. Then for the others, we used for loops*.*
We didn’t prioritize performance when searching the arrays in our examples because the arrays are small. However, if we were to search larger arrays, we’d need to make sure to avoid loops for better performance.