I was trying to check if an array contained a value and I found Check if a Bash array contains a value
It did not work for me, and it was because I decided to remove the spaces surrounding the quotes, like this:
words=(aa bb cc)
[[ " ${words[@]} " =~ " a " ]] && echo "YES" || echo "NO"; # This is the real answer, and it works
------
[[ "${words[@]}" =~ "a" ]] && echo "YES" || echo "NO"; # This does not work. Why???
- Whats the difference when you surround them with spaces or when you dont?
And for my curiosity. In the previous question I mentioned, some answers/comments go with:
${array[*]}
, and others with ${array[@]}
- Do they both "iterate" through the loop in the same way?
CodePudding user response:
[[ string =~ regex ]]
checks if regex
matches any substring of string
. That operator does not iterate over your array entries as for entry in "${words[@]}"
would do. It cannot even handle arrays.
[[ " ${words[@]} " =~ " a " ]]
is only a hack for finding array elements. The array is converted into a single string where all array entries are surrounded by spaces. Then, we search for an element using a string search. This only works reliably, if the array entries themselves do not contain any spaces.
For the difference between ${array[*]}
and ${array[@]}
see bash's manual:
If the word is double-quoted,
${name[*]}
expands to a single word with the value of each array member separated by the first character of the IFS variable [= a space by default], and${name[@]}
expands each element of name to a separate word.
So in this case, *
would be the logical way to write [[ " ${words[*]} " =~ " a " ]]
, because it is equivalent to [[ " aa bb cc " =~ " a " ]]
.
That @
works here too is somewhat strange, because [[ " aa" "bb" "cc " =~ " a " ]]
gives a syntax error. Bash tolerating the misused @
in [[
is probably an undocumented "feature" related to the (documented) disabled word-splitting inside [[
. For the basic POSIX test command [
the difference between *
and @
works as expected, meaning a=("x" "=" "y"); [ "${a[@]}" ]
fails because x != y.