On piping in shell scripts and var scoping

Memento:

When writing shell scripts keep an eye on subshell creation to avoid unexpected results.

Today I was doing something along these lines:

#!/bin/sh

TOT=0

seq 1 3 | \
while read n;
do
  TOT=$(expr -- $TOT + $n)
  echo $TOT
done

echo $TOT

Which led to this output:
1
3
6
0

Definitely not what I would have expected.

Fortunately the web came to the rescue, see this detailed explanation of what's going on here. It turned out that piping a command into a while loop makes bash to fork a subshell, so the variable values are not preserved when the subshell completes its execution.

You can workaround the issue by putting the output of the command into a HEREDOC string and redirecting that into the loop:

#!/bin/sh

TOT=0

while read n;
do
  TOT=$(expr -- $TOT + $n)
  echo $TOT
done <<EOF 
$(seq 1 3)
EOF

echo $TOT

Which gives:
1
3
6
6


CommentiCondividi contenuti

Thanks alot! I've been

Ritratto di evil79genius

Thanks alot! I've been looking for such an elegant solution for a long time!

Invia nuovo commento

Il contenuto di questo campo è privato e non verrà mostrato pubblicamente. If you have a Gravatar account associated with the e-mail address you provide, it will be used to display your avatar.
  • Indirizzi web o e-mail vengono trasformati in link automaticamente
  • Elementi HTML permessi: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Linee e paragrafi vanno a capo automaticamente.

Ulteriori informazioni sulle opzioni di formattazione

CAPTCHA
Questa domanda serve a verificare che il form non venga inviato da procedure automatizzate
h
9
d
P
3
3
Enter the code without spaces.