Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Surprising array expansion behaviour

I've been surprised with the line marked (!!) in the following example:

log1 () { echo $@; }
log2 () { echo "$@"; }

X=(a b)
IFS='|'

echo ${X[@]}   # prints a b
echo "${X[@]}" # prints a b
echo ${X[*]}   # prints a b
echo "${X[*]}" # prints a|b
echo "---"
log1 ${X[@]}   # prints a b
log1 "${X[@]}" # prints a b
log1 ${X[*]}   # prints a b
log1 "${X[*]}" # prints a b (!!)
echo "---"
log2 ${X[@]}   # prints a b
log2 "${X[@]}" # prints a b
log2 ${X[*]}   # prints a b
log2 "${X[*]}" # prints a|b

Here is my understanding of the behavior:

  • ${X[*]} and ${X[@]} both expand to a b
  • "${X[*]}" expands to "a|b"
  • "${X[@]}" expands to "a" "b"
  • $* and $@ have the same behavior as ${X[*]} and ${X[@]}, except for their content being the parameters of the program or function

This seems to be confirmed by the bash manual.

In the line log1 "${X[*]}", I therefore expect the quoted expression to expand to "a|b", then to be passed to the log1 function. The function has a single string parameter which it displays. Why does something else happen?

It'd be cool if your answers were backed by manual/standard references!

like image 641
Norswap Avatar asked Jul 28 '15 12:07

Norswap


2 Answers

IFS is used not just to join the elements of ${X[*]}, but also to split the unquoted expansion $@. For log1 "${X[*]}", the following happens:

  1. "${X[*]}" expands to a|b as expected, so $1 is set to a|b inside log1.
  2. When $@ (unquoted) is expanded, the resulting string is a|b.
  3. The unquoted expansion undergoes word-splitting with | as the delimiter (due to the global value of IFS), so that echo receives two arguments, a and b.
like image 149
chepner Avatar answered Sep 18 '22 04:09

chepner


That's because $IFS is set to |:

(X='a|b' ; IFS='|' ; echo $X)

Output:

a b

man bash says:

IFS The Internal Field Separator that is used for word splitting after expansion ...

like image 39
choroba Avatar answered Sep 20 '22 04:09

choroba