Doomrammer
Doomrammer

Reputation: 13

How to read from variable by line

I need to read from a variable line by line, do some operations with every line and then work with the data afterwards. I have to work in sh.

I already tried this, but $VAR is empty since I assume, that I saved into it in a subshell

#!/bin/sh POSIXLY_CORRECT=yes
STRING="a\nb\nc\n" 
echo $STRING | while read line; do
*some operations with line* 
VAR=$(echo "$VAR$line") 
done 
echo $VAR

I also tried redirecting a variable...

done <<< $STRING
done < $(echo $STRING)
done < < $(echo $STRING)

...and so on, but only got No such file or Redirection unexpected

Please help.

Upvotes: 1

Views: 330

Answers (1)

John Kugelman
John Kugelman

Reputation: 361605

As you've guessed, variable assignments in a subshell aren't seen by the parent, and the commands in a pipelines are run in subshells.

Having to work in plain sh is a real buzzkill. All right, all right, here are a few ideas. One is to extend the life of the subshell and do your work after the loop ends:

string="a
b
c" 
echo "$string" | {
    var=
    while IFS= read -r line; do
        *some operations with line* 
        var=$var$line
    done 
    echo "$var"
}

Another is to use a heredoc (<<), since sh doesn't have herestrings (<<<).

var=
while IFS= read -r line; do
    *some operations with line* 
    var=$var$line
done <<STR
$var
STR

Other improvements:

  • Escapes aren't interpreted in string literals, so if you want literal newlines put literal newlines, not \n.
  • Make sure to empty out $var with var=. You don't want an environment variable leaking into your script.
  • Quote variable expansions. Not needed in assignments, though.
  • $(echo foo) is an anti-pattern: you can just write foo.
  • It's best to keep variables lowercase. All uppercase is reserved for shell variables.
  • Use IFS= and -r to keep read from stripping leading whitespace or interpreting backslashes.

Upvotes: 2

Related Questions