SETUP:
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin21)
Copyright (C) 2007 Free Software Foundation, Inc.
TEST:
check_this() { echo " FIRST: {$1} SECOND: {$2} THIRD: {$3}"; }
foo=(1 2 3)
expression="${foo[@]}"
echo "via expression:"
check_this "$expression"
echo "directly:"
check_this "${foo[@]}"
OUTPUT:
via expression:
FIRST: {1 2 3} SECOND: {} THIRD: {}
directly:
FIRST: {1} SECOND: {2} THIRD: {3}
QUESTION(s):
"${foo[@]}"
not expand to a single string?directly
case above behave the via variable
case?${foo[*]}
and ${foo[@]}
actually is and what the quoting operation does to it.
- what is happening here?
- why does "${foo[@]}" not expand to a single string?
Because that's the explicitly defined behavior -- and a very useful one. When an array-valued variable indexed by @
is expanded inside double quotes, the result is a separate word for each element, or nothing if there are no elements.
- how can I make the directly case above behave the via variable case?
By using "${foo[*]}"
instead of "${foo[@]}"
.
- Please, explain what a construct ${foo[*]} and ${foo[@]} actually is and what the quoting operation does to it.
Both ${foo[*]}
and ${foo[@]}
represent a sequence of the elements of array-valued variable foo
. They differ only with respect to their behavior when expanded inside double quotes, exactly as you are exploring.
When expanded inside double quotes, ${foo[*]}
gives you a single string containing a list of all the elements, separated by the first character in $IFS
(usually a space). If there are no elements then the result is equivalent to an empty pair of quotes (""
). This is approximately as if you had instead written "${foo[0]} ${foo[1]} ${foo[2]} ..."
.
When expanded inside double quotes, ${foo[@]}
gives you a separate string for each element. If there are no elements then the result is equivalent to nothing at all. This is approximately as if you had instead written "${foo[0]}" "${foo[1]}" "${foo[2]}" ...
. Of the two, this is usually the one you want in practice.
These differences are analogous to those between $*
and $@
.
Perhaps it would be a mnemonic aid to associate *
with "all" and @
with "each".