Home > Mobile >  Bash diference between quotes with/without space
Bash diference between quotes with/without space

Time:07-18

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???
  1. 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[@]}

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

  • Related