Bash: reading a multiline string in multiple variables

How can I assign a newline delimited string eg. from 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 <<<

but couldn't get this to work.

Can this be done in bash at all?

+3


source to share


2 answers


Reading the default input delimiter is \ n

{ read a; read b; read c;} <<< "${s}"

      

-d char: allows you to specify a different input delimiter

For example, there is no SOH (1 ASCII) character in the input line

IFS=$'\n' read -r -d$'\1' a b c <<< "${s}"

      



EDIT: -d can take a null argument, the space is required between the -d and null arguments:

IFS=$'\n' read -r -d '' a b c <<< "${s}"

      

EDIT: Following a 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[@]}"

      

+2


source


You are looking for a command readarray

, not read

.

readarray -t lines <<< "$s"

      

(In theory, $s

there is no need to quote here. If you are not using bash

4.4 or newer, I would still quote it due to some bugs in previous versions bash

.)



Once the strings are in the array, you can assign separate variables if you need

a=${lines[0]}
b=${lines[1]}
c=${lines[2]}

      

+2


source







All Articles