Bash scripting: using ‘read’ without a loop

Another post in the “note to myself” style.

For anyone who does bash scripting, the command read is a well known tool. A usual task that we use read for it is to process the output of another command in a while loop, line by line, picking up a few fields and doing something with them. A stupid example:

sysctl -a 2> /dev/null | grep = | while read PARM DUMMY VALUE
do
  echo "Value for $PARM is $VALUE"
done

That is: we read the output of sysctl, line by line, selecting only the lines that contain a = sign, then read the name of the setting and its value in PARM and VALUE respectively, and do something with those values. So far so good.

Based on what we have just seen, it’s easy to expect that this:

echo foobar 42 | read PARM VALUE
echo "Value for $PARM is $VALUE"

would print “Value for foobar is 42“. But it doesn’t:

Value for  is 

So, where did those values go? Did read work at all? In hindsight I can tell you: yes, it worked, but those values have disappeared as soon as read was done with them. To both parse them and use them you have to run both read and the commands using the variables in the same subshell. This works:

echo foobar 42 | ( read PARM VALUE ; echo "Value for $PARM is $VALUE" )

Or even

echo foobar 42 | (
    read PARM VALUE
    echo "Value for $PARM is $VALUE"
)

This will print “Value for foobar is 42”, as expected.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.