4

I don't understand why "${ARRAY[@]}" gets expanded to multiple words, when it's quoted ("...")?

Take this example:

IFS=":" read -ra ARRAY <<< "foo:bar:baz"
for e in "${ARRAY[@]}"; do echo $e; done
foo
bar
baz

Any other variable that I expand in quotes, say "${VAR}", results in a single word:

VAR="foo bar baz"
for a in "${VAR}"; do echo $a; done
foo bar baz

Can anyone explain this to a novice Linux user?

Shuzheng
  • 4,023
  • 1
  • 31
  • 71
  • `${array[@]}` and `${array[*]}` are supposed to act analogously to `$@` and `$*`. That's a thing called "consistency". –  Jan 17 '20 at 17:27
  • The consistency extends (at least [in practice](https://stackoverflow.com/a/57811912/10306503)) to other forms like `"${@:2:4}"` vs. `"${array[@]:2:4}"` or `"${@/pat/repl}"` vs `"${array[@]/pat/repl}"` vs. their `*` forms. –  Jan 17 '20 at 17:37

1 Answers1

12

Because arrays when indexed with @ and double quoted expand to a list of the elements. It's documented in man bash under "Arrays":

If the word is double-quoted, ... ${name[@]} expands each element of name to a separate word.

This behaviour is required if you don't want each element to be subject to word splitting on $IFS characters and globbing (i.e. expansion of *, ?, or [...]).

#!/bin/bash
arr=(a 'b c' d)
for el in  ${arr[@]}  ; do echo "1: $el" ; done
for el in "${arr[@]}" ; do echo "2: $el" ; done

Output:

1: a
1: b
1: c
1: d
2: a
2: b c
2: d

If you want the array expanded as a single string (with the elements of the array delimited by the first character of $IFS, by default a space), then use "${arr[*]}".

The "${arr[@]}" and "${arr[*]}" syntax for array expansion is analogous to "$@" and "$*" for the positional parameters.

choroba
  • 45,735
  • 7
  • 84
  • 110
  • 3
    It's not really *whitespace*, it's characters of `$IFS` (SPC, TAB, NL by default) and wildcard characters. IMO, the wording is a bit misleading here. It's not *useful* it's *required*. You don't leave parameter expansions unquoted unless you want that split+glob. Split+glob on an array hardly ever makes sense, so array expansions should almost always be quoted. – Stéphane Chazelas Jan 18 '20 at 08:23
  • @StéphaneChazelas: Updated. – choroba May 04 '23 at 16:07
  • That *This behaviour is required if an element contains whitespace or characters from the $IFS variable* wording still doesn't make much sense. Maybe something like *Without the quoting, each element would also be subject to split+glob so not do what you want if they contained characters of `$IFS` (not whitespace) or glob operators such as `*`, `?` or `[...]`*. – Stéphane Chazelas May 04 '23 at 16:14