How can I assign a newline-separated string with e.g. three lines to three variables ?
# test string
s='line 01
line 02
line 03'
# this doesn't seem to make any difference at all
IFS=$'\n'
# first naive attempt
read a b c <<< "${s}"
# this prints 'line 01||':
# everything after the first newline is dropped
echo "${a}|${b}|${c}"
# second attempt, remove quotes
read a b c <<< ${s}
# this prints 'line 01 line 02 line 03||':
# everything is assigned to the first variable
echo "${a}|${b}|${c}"
# third attempt, add -r
read -r a b c <<< ${s}
# this prints 'line 01 line 02 line 03||':
# -r switch doesn't seem to make a difference
echo "${a}|${b}|${c}"
# fourth attempt, re-add quotes
read -r a b c <<< "${s}"
# this prints 'line 01||':
# -r switch doesn't seem to make a difference
echo "${a}|${b}|${c}"
I also tried using echo ${s} | read a b c
instead of <<<
, but couldn't get that to work either.
Can this be done in bash at all ?
read default input delimiter is \n
{ read a; read b; read c;} <<< "${s}"
-d char : allows to specify another input delimiter
For example is there is no character SOH (1 ASCII) in input string
IFS=$'\n' read -r -d$'\1' a b c <<< "${s}"
We set IFS
to $'\n'
because IFS default value is :
$ printf "$IFS" | hd -c
00000000 20 09 0a | ..|
0000000 \t \n
0000003
EDIT: -d can take a null argument the space is mandatory between -d and null argument:
IFS=$'\n' read -r -d '' a b c <<< "${s}"
The read
builtin documentation is available by typing help read
at the bash prompt.
EDIT: after comment about a solution for any number of lines
function read_n {
local i s n line
n=$1
s=$2
arr=()
for ((i=0;i<n;i+=1)); do
IFS= read -r line
arr[i]=$line
done <<< "${s}"
}
nl=$'\n'
read_n 10 "a${nl}b${nl}c${nl}d${nl}e${nl}f${nl}g${nl}h${nl}i${nl}j${nl}k${nl}l"
printf "'%s'\n" "${arr[@]}"
You are looking for the readarray
command, not read
.
readarray -t lines <<< "$s"
(Theoretically, $s
does not need to be quoted here. Unless you are using bash
4.4 or later, I would quote it anyway, due to some bugs in previous versions of bash
.)
Once the lines are in an array, you can assign the separate variables if you need to
a=${lines[0]}
b=${lines[1]}
c=${lines[2]}
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