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 functionThis 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!
IFS is used not just to join the elements of ${X[*]}, but also to split the unquoted expansion $@. For log1 "${X[*]}", the following happens:
"${X[*]}" expands to a|b as expected, so $1 is set to a|b inside log1.$@ (unquoted) is expanded, the resulting string is a|b.| as the delimiter (due to the global value of IFS), so that echo receives two arguments, a and b.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 ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With