我需要验证一些程序输出。我知道输出包含三行,我想存储在不同的变量中以便于访问。我尝试了以下几种变体而没有成功。
IFS=$'\n' read line1 line2 line3 <<< $(grep pattern file.log)
IFS='' read line1 line2 line3 <<< $(grep pattern file.log)
是否可以将read
和<<<
结合起来做我想要的事情?怎么样?
如果不可能,解释是什么?你有什么选择吗?
谢谢。
答案 0 :(得分:5)
{
read line1
read line2
read line3
} < <(grep pattern file.log)
我觉得在一个herestring($()
)之后放置一个命令替换(<<<
)
是一种不必要的扭曲,就像试图让read
一次读取多行一样。这种情况是复合命令中的多个read
是自然解决方案。
答案 1 :(得分:1)
将IFS
设为\n
并将-d ''
传递给read
。您也可以使用进程替换而不是here string
while IFS=$'\n' read -d'' -r line1 line2 line3; do :; done < <(grep pattern file.log)
答案 2 :(得分:1)
好吧,我已经找到了如何让它发挥作用。它取决于双引号的使用。
首先我尝试了这个:
data=$(grep pattern file.log)
IFS=$'\n' read -d '' -r line1 line2 line3 <<< "$data"
然后发现如果我保留双引号,变量不是绝对必要的:
IFS=$'\n' read -d '' -r line1 line2 line3 <<< "$(grep pattern file.log)"
默认情况下,换行符表示数据结束。为避免read
在第一行后停止工作,我使用-d ''
覆盖默认值。
默认情况下,字段分隔符为<space><tab><newline>
。由于我想读取整行,我将IFS设置为$'\n'
。
请注意,-r
不是解决方案的核心。我添加它是为了避免在输入中绊倒最终的反斜杠。
修改
使用read
和<<<
有一个微妙但重要的缺点:空行将完全消失。
data="1
3"
IFS=$'\n' read -d '' -r line1 line2 line3 <<< "$data"
echo ${line1:-blank}
echo ${line2:-blank}
echo ${line3:-blank}
output:
1
3
blank
如果您尝试使用-a
IFS=$'\n' read -d '' -r -a line_ar <<< "$data"
echo ${line_ar[0]:-blank}
echo ${line_ar[1]:-blank}
echo ${line_ar[2]:-blank}
output:
1
3
blank
但是,您仍将获得具有如下结构的所有行:
while read -r line ; do
echo ${line:-blank}
done <<< "$data"
output:
1
blank
3
如果行数非常有限,那么你最好使用kojiro建议的多次读取。再说一次,使用<<<
:
{
read -r line1
read -r line2
read -r line3
} <<< "$data"
echo ${line1:-blank}
echo ${line2:-blank}
echo ${line3:-blank}
请记住将"$var"
括在双引号内以扩展换行符。
答案 3 :(得分:0)
使用数组
read -a array < <(grep pattern file.log)
# Optional
line1=${array[0]}
line2=${array[1]}
line3=${array[2]}
但是,我建议kojiro's answer。
答案 4 :(得分:0)
while read -r arry[x]; do
((x++));
done < <(grep pattern file.log)
这将创建一个名为arry
的数组,3行将属于从0开始的每个索引。