While-loop over lines from variable in bash
Asked Answered
P

2

6

Assume a file file with multiple lines.

$ cat file
foo
bar
baz

Assume further that I wish to loop through each line with a while-loop.

$ while IFS= read -r line; do
$   echo $line
$   # do stuff
$ done < file
foo
bar
baz

Finally, please assume that I wish to pass lines stored in a variable rather than lines stored in a file. How can I loop through lines that are saved as a variable without receiving the below error?

$ MY_VAR=$(cat file)
$ while IFS= read -r line; do
$   echo $line
$   # do stuff
$ done < $(echo "$MY_VAR")
bash: $(echo "$MY_VAR"): ambiguous redirect
Padriac answered 26/6, 2017 at 20:1 Comment(2)
echo $line is not the same as echo "$line". See BashPitfalls #14.Wellbeing
Also, all-caps variable names are used for variables with meaning to the shell or OS, whereas names with lowercase characters are guaranteed not to conflict with system operation. See pubs.opengroup.org/onlinepubs/9699919799/basedefs/…, fourth paragraph.Wellbeing
W
6

You have several options:

  • A herestring (note that this is a non-POSIX extension): done <<<"$MY_VAR"
  • A heredoc (POSIX-compliant, will work with /bin/sh):

    done <<EOF
    $MY_VAR
    EOF
    
  • A process substitution (also a non-POSIX extension, but using printf rather than echo makes it more predictable across shells that support it; see the APPLICATION USAGE note in the POSIX spec for echo): done < <(printf '%s\n' "$MY_VAR")


Note that the first two options will (in bash) create a temporary file on disk with the variable's contents, whereas the last one uses a FIFO.

Wellbeing answered 26/6, 2017 at 20:4 Comment(1)
Thanks for the detailed explanations as well as the useful comments above. Much appreciated.Padriac
W
5

< needs to be followed by a filename. You can use a here-string:

done <<< "$MY_VAR"

or process substitution:

done < <(echo "$MY_VAR")
Winfredwinfrey answered 26/6, 2017 at 20:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.