bash:将多行字符串读入多个变量

ssc*_*ssc 4 string bash

如何将一个以换行符分隔的字符串(例如三行)分配给三个变量?

# 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}"
Run Code Online (Sandbox Code Playgroud)

我也尝试使用echo ${s} | read a b c而不是<<<,但也无法让它工作。

这可以在 bash 中完成吗?

che*_*ner 8

您正在寻找readarray命令,而不是read.

readarray -t lines <<< "$s"
Run Code Online (Sandbox Code Playgroud)

(理论上,$s这里不需要引用。除非你使用bash4.4或更高版本,否则我无论如何都会引用它,因为以前版本的一些错误bash。)

将行放入数组后,如果需要,您可以分配单独的变量

a=${lines[0]}
b=${lines[1]}
c=${lines[2]}
Run Code Online (Sandbox Code Playgroud)


Nah*_*eul 7

读取默认输入分隔符是\n

{ read a; read b; read c;} <<< "${s}"
Run Code Online (Sandbox Code Playgroud)

-d char : 允许指定另一个输入分隔符

例如,输入字符串中没有字符 SOH (1 ASCII)

IFS=$'\n' read -r -d$'\1' a b c <<< "${s}"
Run Code Online (Sandbox Code Playgroud)

我们设置IFS$'\n'因为 IFS 默认值为:

$ printf "$IFS" | hd -c
00000000  20 09 0a                                          | ..|
0000000      \t  \n                                                    
0000003
Run Code Online (Sandbox Code Playgroud)

编辑: -d 可以采用空参数 -d 和空参数之间的空格是强制性的:

IFS=$'\n' read -r -d '' a b c <<< "${s}"
Run Code Online (Sandbox Code Playgroud)

read内置文档可通过打字help read在bash提示符。

编辑:在评论任意多行的解决方案之后

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[@]}"
Run Code Online (Sandbox Code Playgroud)