59

Is it possible to format this sample:

for i in string1 string2 stringN
do
 echo $i
done

to something similar to this:

for i in 
string1
string2
stringN
do
 echo $i
done

EDIT: Sorry for confusion, didn't realize that there was different methods of executing script - sh <scriptname> versus bash <scriptname> and also this thing which I cannot name right now - #!/bin/sh and #!/bin/bash :)

8 Answers8

101

Using arrays in bash can aid readability: this array syntax allows arbitrary whitespace between words.

strings=(
    string1
    string2
    "string with spaces"
    stringN
)
for i in "${strings[@]}"; do
    echo "$i"
done
glenn jackman
  • 85,964
10

You can escape the linebreak with a backslash:

$ for i in \
> hello \
> world
> do
> echo $i
> done
hello
world
$
Andy Dalton
  • 13,993
6
list='a b c d'
for element in $list;do 
    echo "$element"
done
Bart
  • 2,221
guest
  • 71
  • You are missing semicolons! – 41754 Jul 23 '19 at 08:46
  • Note that this would work as long as each string is a separate word. As soon as you have spaces in your strings, the spaces would break the string apart into multiple words. Also, if the $list string contains filename globbing characters (list='* * * *'), the shell would potentially replace these with matching filenames. – Kusalananda Jul 23 '19 at 09:29
4

You may escape the newlines before/after each item that you loop over:

for i in \
    string1 \
    string2 \
    stringN
do
   printf '%s\n' "$i"
done

Or, for this simple example:

printf '%s\n' string1 string2 stringN

which has the same result.

Related:

Variation using a bash array:

strings=(
    string1
    string2
    stringN
)

printf '%s\n' "${strings[@]}"
Kusalananda
  • 333,661
2

If switching to zsh is an option:

for string (
  string1
  'other string'
  etc..
) printf '%s\n' "$string"
1

Same thing, less text:

array=(
        string{1..7}
)

for i in "${array[@]}"; do
    echo "$i"
done
  • string1 etc. aren’t the literal values to be displayed, they’re placeholders, so this approach doesn’t work. – Stephen Kitt Jan 28 '20 at 12:59
  • if so, why bothering array ( … )? just do for i in string{1..7}; do echo "$i"; done; even printf '%s\n' string{1..7} – αғsнιη Jan 28 '20 at 13:12
1

You can loop over a list of strings (with and without embedded spaces) as follows:

#!/usr/bin/env bash

var1="text-without-spaces" var2="text with spaces"

for item in "${var1}" "${var2}" "more-without-spaces" "more with spaces"; do echo "'${item}'" done

NB You can leave out braces around variable identifiers in the above example e.g. use $var1 instead of ${var1}.

This outputs:

'text-without-spaces'
'text with spaces'
'more-without-spaces'
'more with spaces'

Petr Vepřek
  • 109
  • 3
0

You can use the loop command, available here, like so:

$ loop 'echo "$ITEM"' --for string1,string2,string3

or, if you have the list in a file, one per line:

$ <file_list.txt loop 'echo "$ITEM"'

Beware however that it runs one sh invocation per item (to interpret that code whilst the item is stored in the ITEM environment variable), and that it currently chokes on sequences of bytes that don't form valid characters in UTF-8 (even if the locale's charmap is not UTF-8).