Bash ships with a number of built-in commands that you can use on the command line or in your shell scripts.
In this article, we’ll explore the built-in read
command.
Bash read
Built-in
read
is a bash built-in command that reads a line from the standard input (or from the file descriptor) and split the line into words. The first word is assigned to the first name, the second one to the second name, and so on.
The general syntax of the read
built-in takes the following form:
read [options] [name...]
To illustrate how the command works, open your terminal, type read var1 var2
, and hit “Enter”. The command will wait for the user to enter the input. Type two words and press “Enter”.
read var1 var2
Hello, World!
The words are assigned to the names that are passed to the read
command as arguments. Use echo
or printf
to verify it:
echo $var1
echo $var2
Hello,
World!
Instead of typing on the terminal, you can pass the standard input to read
using other methods such as piping, here-string, or heredoc :
echo "Hello, World!" | (read var1 var2; echo -e "$var1 \n$var2")
read
and echo
are enclosed in parentheses and executed in the same subshell.Hello,
World!
Here is an example using a here string and printf
:
read -r var1 var2 <<< "Hello, World!"
printf "var1: %s \nvar2: %s\n" "$var1" "$var2"
Var1: Hello,
Var2: World!
When no argument is provided to the read
command, the entire line is assigned to the REPLY
variable:
echo "Hello, world!" | (read; echo "$REPLY")
Hello, World!
If the number of arguments supplied to read
is bigger than the number of words read from the input, the remaining words are assigned to the last name:
echo "Linux is awesome." | (read var1 var2; echo -e "Var1: $var1 \nVar2: $var2")
Var1: Linux
Var2: is awesome.
Otherwise, if the number of arguments is less than the number of names, an empty value is assigned to the remaining names:
echo "Hello, World!" | (read var1 var2 var3; echo -e "Var1: $var1 \nVar2: $var2 \nVar3: $var3")
Var1: Hello,
Var2: World!
Var3:
By default, read
interprets the backslash as an escape character, which sometimes may cause unexpected behavior. To disable backslash escaping, invoke the command with the -r
option.
Below is an example showing how read
works when invoked with and without the -r
option:
read <<< "Hello, \tWorld!"
printf %s "$REPLY"
Hello, tWorld!
read -r <<< "Hello, \tWorld!"
printf %s "$REPLY"
Hello, \tWorld!
Generally, you should always use read
with the -r
option.
Changing the Delimiter
The default behavior of read
is to split the line into words using one or more spaces, tabs, and newline as delimiters. To use another character as a delimiter, assign it to the IFS
variable (Internal Field Separator).
echo "Linux:is:awesome." | (IFS=":" read -r var1 var2 var3; echo -e "$var1 \n$var2 \n$var3")
Linux
is
awesome.
When IFS
is set to a character other than space or tab, the words are separated by exactly one character:
echo "Linux::is:awesome." | \
(IFS=":" read -r var1 var2 var3 var4; echo -e "Var1: $var1 \nVar2: $var2 \nVar3: $var3 \nVar4: $var4")
The line is separated in four words. The second word is an empty value representing the segment between the delimiters. It is created because we used two delimiter characters next to each other(::
).
Var1: Linux
Var2:
Var3: is
Var4: awesome.
You can use more than one delimiter to split the line. When specifying multiple delimiters, assign the characters to the IFS
variable without a space between them.
Here is an example using _
an -
as delimiters:
echo 'Linux_is-awesome.' | (IFS="-_" read -r var1 var2 var3; echo -e "$var1 \n$var2 \n$var3")
Linux
is
awesome.
Prompt String
When writing interactive bash scripts, you can use the read
command to get the user input.
To specify a prompt string, use the -p
option. The prompt is printed before the read
is executed and doesn’t include a newline.
Here is a simple example:
read -r -p "Are you sure?"
Generally, you would use the read
command inside a while
loop to force the user to give one of the expected answers.
The code below will prompt the user for system reboot :
while true; do
read -r -p "Do you wish to reboot the system? (Y/N): " answer
case $answer in
[Yy]* ) reboot; break;;
[Nn]* ) exit;;
* ) echo "Please answer Y or N.";;
esac
done
If the shell script asks users to enter sensitive information, like password, use the -s
option that tells read
not to print the input on the terminal:
read -r -s -p "Enter your password: "
Assign the Words to Array
To assign the words to an array instead of variable names, invoke the read
command with the -a
option:
read -r -a MY_ARR <<< "Linux is awesome."
for i in "${MY_ARR[@]}"; do
echo "$i"
done
Linux
is
awesome.
When both an array and a variable name are given, all words are assigned to the array.
Conclusion
The read
command is used to split a line of input into words.
If you have any questions or feedback, feel free to leave a comment.