3

With the following code:

#! /bin/bash                         
                                     
declare -a arr=("element1"           
                "element2" "element3"
                "element4" )         
echo "1"                             
echo "${arr[@]}"                     
                                     
echo "2"                             
echo ${arr[*]}                       

The output is:

1
element1 element2 element3 element4
2
element1 element2 element3 element4

So the output is the same.

So when is mandatory use one approach over the other?

2

1 Answer 1

9

Compare the output of these three loops:

#!/bin/bash

declare -a arr=("this is" "a test" "of bash")

echo "LOOP 1"
for x in ${arr[*]}; do
  echo "item: $x"
done
echo

echo "LOOP 2"
for x in "${arr[*]}"; do
  echo "item: $x"
done
echo

echo "LOOP 3"
for x in "${arr[@]}"; do
  echo "item: $x"
done

The above script will produce this output:

LOOP 1
item: this
item: is
item: a
item: test
item: of
item: bash

LOOP 2
item: this is a test of bash

LOOP 3
item: this is
item: a test
item: of bash

The use of "${array[@]}" in double quotes preserves the items in the array, even if they contain whitespace, whereas you lose that information using either "${array[*]}" or ${array[*]}.


This is explained in the "Arrays" section of the bash(1) man page, which says:

Any element of an array may be referenced using ${name[subscript]}. The braces are required to avoid conflicts with pathname expansion. If subscript is @ or *, the word expands to all members of name. These subscripts differ only when the word appears within double quotes. If the word is double-quoted, ${name[*]} expands to a single word with the value of each array member separated by the first character of the IFS special variable, and ${name[@]} expands each element of name to a separate word...

6
  • Practically the difference applies for iteration and not for the direct output as I shared in the original post - should I assume it is the unique difference? Commented Feb 7, 2022 at 20:54
  • Consider to add: echo "LOOP 4" for x in ${arr[@]}; do echo "item: $x" done it is such as your Loop 3 but without "" Commented Feb 7, 2022 at 21:08
  • 1
    Yeah, I intentionally skipped that because -- per the quoted docs -- it's going to be identical to the LOOP 1 output.
    – larsks
    Commented Feb 7, 2022 at 21:21
  • 1
    W/r/t to your first quesiton, the difference isn't just in iteration. Compare someprogram "${arr[@]}" vs any other variant of that expression -- the arguments passed to the program will reflect exactly the differences we see in the above loop examples.
    – larsks
    Commented Feb 7, 2022 at 21:22
  • 2
    @ManuelJordan echo hides the difference. Note that echo "this is a test of bash" and echo "this" "is" "a" "test" "of" "bash" both print exactly the same thing, despite the actual arguments passed to echo being very different (and that difference will matter in almost all situations -- echo is the exception here). Commented Feb 7, 2022 at 21:57

Not the answer you're looking for? Browse other questions tagged .