3

我需要验证一些程序输出。我知道输出正好包含三行,我想将它们存储在不同的变量中以便于访问。我尝试了以下几种变体,但均未成功。

IFS=$'\n' read line1 line2 line3 <<< $(grep pattern file.log)
IFS='' read line1 line2 line3 <<< $(grep pattern file.log)

是否可以结合read<<<做我想做的事?如何?

如果不可能,有什么解释?你建议什么替代方案?

谢谢你。

4

5 回答 5

5
{
    read line1
    read line2
    read line3
} < <(grep pattern file.log) 

我觉得$()在字符串 ( ) 之后放置命令替换 ( <<<) 是一种不必要的扭曲,就像试图read一次读取多行一样。这是复合命令中的多个reads 是自然解决方案的情况。

于 2013-07-10T18:29:16.597 回答
2

好吧,我已经找到了如何让它发挥作用。它取决于双引号的使用。

首先我尝试了这个:

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不是解决方案的核心。我添加它是为了避免在我的输入中遇到最终的反斜杠。

编辑

使用readand<<<有一个微妙但重要的缺点:空白行将完全消失。

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"内部双引号括起来以扩展换行符。

于 2013-07-10T19:28:54.433 回答
1

设置IFS\n并传递-d ''read。您也可以使用进程替换而不是此处的字符串

while IFS=$'\n' read -d'' -r line1 line2 line3; do :; done < <(grep pattern file.log)
于 2013-07-10T18:15:22.730 回答
0

使用数组

read -a array < <(grep pattern file.log)
# Optional
line1=${array[0]}
line2=${array[1]}
line3=${array[2]}

但是,我会推荐小次郎的回答

于 2013-07-10T18:31:20.947 回答
0
while read -r arry[x]; do 
    ((x++)); 
done < <(grep pattern file.log)

这将创建一个名为的数组arry,3 行将属于从 ​​0 开始的每个索引。

于 2013-07-10T18:33:04.450 回答