How to use the read command in Bash?

BashBuilt In

Bash Problem Overview


When I try to use the read command in Bash like this:

echo hello | read str
echo $str

Nothing echoed, while I think str should contain the string hello. Can anybody please help me understand this behavior?

Bash Solutions


Solution 1 - Bash

The read in your script command is fine. However, you execute it in the pipeline, which means it is in a subshell, therefore, the variables it reads to are not visible in the parent shell. You can either

  • move the rest of the script in the subshell, too:

      echo hello | { read str
        echo $str
      }
    
  • or use command substitution to get the value of the variable out of the subshell

      str=$(echo hello)
      echo $str
    

or a slightly more complicated example (Grabbing the 2nd element of ls)

    str=$(ls | { read a; read a; echo $a; })
    echo $str

Solution 2 - Bash

Other bash alternatives that do not involve a subshell:

read str <<END             # here-doc
hello
END

read str <<< "hello"       # here-string

read str < <(echo hello)   # process substitution

Solution 3 - Bash

Typical usage might look like:

i=0
echo -e "hello1\nhello2\nhello3" | while read str ; do
    echo "$((++i)): $str"
done

and output

1: hello1
2: hello2
3: hello3

Solution 4 - Bash

The value disappears since the read command is run in a separate subshell: Bash FAQ 24

Solution 5 - Bash

To put my two cents here: on KSH, reading as is to a variable will work, because according to the IBM AIX documentation, KSH's read does affects the current shell environment:

>The setting of shell variables by the read command affects the current shell execution environment.

This just resulted in me spending a good few minutes figuring out why a one-liner ending with read that I've used a zillion times before on AIX didn't work on Linux... it's because KSH does saves to the current environment and BASH doesn't!

Solution 6 - Bash

I really only use read with "while" and a do loop:

echo "This is NOT a test." | while read -r a b c theRest; do  
echo "$a" "$b" "$theRest"; done  

This is a test.
For what it's worth, I have seen the recommendation to always use -r with the read command in bash.

Solution 7 - Bash

You don't need echo to use read

 read -p "Guess a Number" NUMBER

Solution 8 - Bash

Another alternative altogether is to use the printf function.

printf -v str 'hello'

Moreover, this construct, combined with the use of single quotes where appropriate, helps to avoid the multi-escape problems of subshells and other forms of interpolative quoting.

Solution 9 - Bash

Do you need the pipe?

echo -ne "$MENU"
read NUMBER

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDeterminantView Question on Stackoverflow
Solution 1 - BashjpalecekView Answer on Stackoverflow
Solution 2 - Bashglenn jackmanView Answer on Stackoverflow
Solution 3 - BashShizzmoView Answer on Stackoverflow
Solution 4 - Bashl0b0View Answer on Stackoverflow
Solution 5 - BashRAKKView Answer on Stackoverflow
Solution 6 - BashJackDRView Answer on Stackoverflow
Solution 7 - BashEgeView Answer on Stackoverflow
Solution 8 - BashjxqzView Answer on Stackoverflow
Solution 9 - BashmmrtntView Answer on Stackoverflow