I'm studying bash language and an exam track says this:
It should read one input (from standard input) at a time (each entry is a string and then ends with a newline).
My questions are two:
How do I read line by line from standard input in Bash? Until now I used "read string"
but I do not think that it reads a line at a time.
I do not know if this is a stupid question , but once created the script how can I give more lines to the script as input (read from standard input of course). For example from stdin I insert two lines (hello
and world
). How do I give to the bash script these two lines?
- How do I read line by line from standard input in Bash? Until now I used "read string" but I do not think that it reads a line at a time.
The prototype for read
is:
read [options] name[s ...]
read
will read a line
of input into name name1 name2 ...
splitting the line based on the contents of the Internal Field Separator (IFS
). The default for IFS
is ' \t\n'
(that is space
tab
newline
). If you only provide a single variable to read
, you will read the entire line into that variable (unless you have set a new delimiter with the -d
option to read
). If you provide more than one variable, (e.g. read -r name name1
) word splitting will occur based on the current value of IFS
. Meaning if you provide the string hello world
to:
read -r name
name="hello world"
. On the other hand, if you provide the same string to:
read -r name name1
name="hello"
, name1="world"
. What if you have excess words in the line but only 2 variables? Say your string is now "hello big wide world"
, what happens with:
read -r name name1
name="hello"
, name1="big wide world"
. The words in string
are assigned to your variables in order and if there are insufficient variables to hold each word in the string, the last variable will contain all remaining words in the string not previously assigned.
You change how word splitting occurs by altering IFS
. Take a close look at the answer provided by anubhava for an example. You are free to specify any character you would like the words to be split on. (helpful in say parsing a csv
file to set IFS=$',\n'
and have the words split on ','
instead of space)
To ensure you read an entire line into a variable, you can provide only a single variable to read
and set IFS='$\n'
to ensure word splitting only occurs on newline
. (Note: providing the change as part of the while
loop limits the IFS
alteration to the scope of that loop. For example:
while IFS='$\n' read -r line; do
# do whatever with line
done
Will ensure that each line on stdin
will be read into line
while preserving normal word-splitting outside the loop. Inside the loop you can then add each line to an array as anubhava shows in his answer. (to preserve all whitespace IFS=
is used)
You can do something like this:
# array to hold all lines read
lines=()
# read all lines in lines array
while IFS= read -r line; do
lines+=( "$line" )
done < file
# read 3 more lines from stdin
for ((i=0; i<3; i++)); do
read -rp "Enter a line: " line
lines+=( "$line" )
done
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With