80

this question is not the same as Does the shell support sets?

i know lots of script language support list structure, such as python, python, ruby, and javascript, so what about linux shell?

does shell support such syntax?

for i in list:
do
     print i
done

i would first to initialize a list, for example:

ListName = [ item1, item2, ..., itemn ]

then iterate over it

is that possible when programming shell scripts?

Community
  • 1
  • 1
hugemeow
  • 7,777
  • 13
  • 50
  • 63
  • 1
    Note also that Bourne shell / POSIX shell doesn't have arrays. But the `for item in list of items; do` construct is certainly supported in all shells. Note also the convenient use of globbing to loop over a set of files; `for file in a*.dat` constructs a list of tokens by expanding the wildcard (though sadly, many users manage to wreck it by doing something like `for file in $(ls a*.dat)`). – tripleee Sep 07 '12 at 16:41

2 Answers2

142

It supports lists, but not as a separate data structure (ignoring arrays for the moment).

The for loop iterates over a list (in the generic sense) of white-space separated values, regardless of how that list is created, whether literally:

for i in 1 2 3; do
    echo "$i"
done

or via parameter expansion:

listVar="1 2 3"
for i in $listVar; do
    echo "$i"
done

or command substitution:

for i in $(echo 1; echo 2; echo 3); do
    echo "$i"
done

An array is just a special parameter which can contain a more structured list of value, where each element can itself contain whitespace. Compare the difference:

array=("item 1" "item 2" "item 3")
for i in "${array[@]}"; do   # The quotes are necessary here
    echo "$i"
done

list='"item 1" "item 2" "item 3"'
for i in $list; do
    echo $i
done
for i in "$list"; do
    echo $i
done
for i in ${array[@]}; do
    echo $i
done
chepner
  • 497,756
  • 71
  • 530
  • 681
  • What does the @ mean?? – Vini.g.fer Oct 23 '15 at 17:04
  • 3
    It's a special index that causes the expansion to produce all elements of the array, not just one specific element. – chepner Oct 23 '15 at 17:07
  • I didn't get why `for i in "${array[@]}";` prints 3 lines. Since `echo ${array[@]}` prints a single line `item 1 item 2 item 3` , I would expect that `for i in "${array[@]}";` is converted in `for i in "item 1 item 2 item 3";` ; so it would result in a single line `item 1 item 2 item 3`. What am I missing? Thanks in advance – Svech87 Mar 27 '17 at 08:42
  • 1
    `"${array[*]}"` would expand to `"item 1 item 2 item 3"`. `"${array[@]}"` expands to `"item 1" "item 2" "item 3"`; it treats each element as a separate quoted word, rather than a single quoted word containing every element. – chepner Mar 27 '17 at 11:58
  • array only works in bash shell. Is there a way to achieve same in KSH? – Mohammad Azim Jun 07 '18 at 14:17
  • What makes you think `ksh` doesn't support arrays? It does, but the syntax is a little different in places. This answer and its comments isn't the place to explain the differences. – chepner Jun 07 '18 at 16:40
19

For make a list, simply do that

colors=(red orange white "light gray")

Technically is an array, but - of course - it has all list features.
Even python list are implemented with array

DonCallisto
  • 29,419
  • 9
  • 72
  • 100
  • 5
    To iterate over the array, use `for item in ${colors[*]}; do echo $item; done` – neevek Sep 07 '12 at 10:31
  • 13
    @Neevek that won't do what you think it does; "light gray" will be treated as two items "light" and "gray". You need to use `"${colors[@]}"` (`@` not `*`, and quoted). – chepner Sep 07 '12 at 12:15
  • why "light gray" will be treated as two items when * is used? where i can find documents for such details? man sh? – hugemeow Sep 07 '12 at 18:13
  • 2
    Basically that's a historical flaw, `$*` in the Bourne shell didn't work correctly in all situations and so `"$@"` had to be invented. – tripleee Sep 07 '12 at 18:42