-1

I get confused on array syntax in bash. I typically use quotes to enclose strings to loop through, but tutorials typically use parentheses. For kicks I made 4 simple loops. The first two work as I expected by echoing each item in the array, the second two gave unexpected output.

Why does this happen?

LOOP #1

$ List="item1 item2 item3"
$ for f in $List; do echo ${f}; done
item1
item2
item3

LOOP #2

$ List=(item1 item2 item3)
$ for f in ${List[@]}; do echo ${f}; done
item1
item2
item3

LOOP #3

$ List="item1 item2 item3"
$ for f in ${List[@]}; do echo ${f}; done
item1
item2
item3
item2
item3

LOOP #4

$ List=(item1 item2 item3)
$ for f in $List; do echo ${f}; done
item1
9
  • 1
    Always quote ${List[@]}, as otherwise there is no reason to use @ instead of *.
    – chepner
    Commented May 4, 2018 at 19:22
  • The first and 3rd don't have any array involved at all. Unquoted string expansion != array. Commented May 4, 2018 at 19:35
  • ...also, you've got a bunch of quoting issues here; shellcheck.net will catch them automatically, and provide wiki links with explanations. Commented May 4, 2018 at 19:39
  • @Charles. I think your comments get at the crux of what I don't understand. If you could point me to resources that explain what you mean by "Unquoted string expansion != array" and "a bunch of quoting issues", I would appreciate it.
    – bigdoyle
    Commented May 4, 2018 at 20:41
  • In light of haccks comment below I can now see that quotes don't work. I'm just not understanding the reason. (edit: sorry, I cant figure out how to get the formatting to work) $ LISTA="item1 item2 item3" $ printf '%s\n' ${LIST6[2]]} $ LISTB=(item1 item2 item3) $ printf '%s\n' ${LIST7[2]]} item3
    – bigdoyle
    Commented May 4, 2018 at 20:44

2 Answers 2

1

The first two work as I expected by echoing each item in the array, the second two gave unexpected output.

Your fourth loop is equivalent to for f in ${List[0]}; do echo ${f}; done. This is documented in man bash:

Referencing an array variable without a subscript is equivalent to referencing the array with a subscript of 0.

Third loop works but is not printing the original array. Try:

List=(item1 item2 item3)     # Declares array List
printf '%s\n' "${List[@]}"
item1
item2
item3

List="item1 item2 item3"     # Overwrites first element of array... 
                             # ... equivalent to List[0]="item1 item2 item3"
printf '%s\n' "${List[@]}"
item1 item2 item3
item2
item3
3
  • Thanks for the input. I have replaced echo with printf and quoted the variable. Commented May 4, 2018 at 19:52
  • Yes I meant List="item1 item2 item3", I've updated the answer. Commented May 4, 2018 at 20:00
  • 1
    (thumbs-up) re: answer-as-edited. Commented May 4, 2018 at 21:14
0

First 3 snippets should work, but the problem with 3rd is that List="item1 item2 item3" will replace item1 with "item1 item2 item3" and that's why you are getting the output

item1
item2
item3
item2
item3 

Change the name of the variable and it will work

List2="item1 item2 item3"   

In last snippet $List is used without index and this is same as referring to the content of the first element of the array List.

1
  • Ah. I didn't realize that was happening. If I had run #3 first I wouldn't have seen it, or learned it worked that way. Thanks.
    – bigdoyle
    Commented May 4, 2018 at 20:30

Not the answer you're looking for? Browse other questions tagged or ask your own question.