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):
- what is happening here?
- why does
"${foo[@]}"not expand to a single string? - how can I make the
directlycase above behave thevia variablecase? - Please, explain what a construct
${foo[*]}and${foo[@]}actually is and what the quoting operation does to it.
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.By using
"${foo[*]}"instead of"${foo[@]}".Both
${foo[*]}and${foo[@]}represent a sequence of the elements of array-valued variablefoo. 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".