如何使用“\n\n”而不是“\n”while 构造将管道的输出拆分为变量?

how to split output from pipe into variables by using "\n\n" instead of "\n" with while contruct?

我有一个这种格式的数据文件:

name=...
phone=...
address=..

name=...
phone=..
address=...

name=...
phone=...
address=...

并且我尝试使用 while 循环将它分成块,其中有一个空行是“\n\n”。但是下面的这种方法失败了。

cat mydatafile.txt | while read row; do
  echo $row
  # process the data
done

想要的结束状态是一个变量,包含文件中的三行内容,即在循环的每次迭代中row="name=...\nphone=...\naddress=..."

好吧,如果您 100% 确定总会有 3 行是您想要的,然后是 1 行不需要的,您可以这样做:

cat mydatafile.txt | while read row1; do
  read row2
  read row3
  read junk
  row="$row1 $row2 $row3"
  echo $row
  # process the data
done

认为 会从同一个标准输入继续 read,但我不是 100% 确定。

或者您可以创建自己的有限状态自动机(抱歉 - 我只是喜欢它的声音):

recno=0
cat mydatafile.txt | while read foo; do
  let recno=recno+1
  if [ $recno -lt 4 ]
  then
    row="$row $foo"
  fi
  if [ $recno == 4 ]
  then
    echo $row
    # process the data
    recno=0
    row=''
  fi
done
# Here you might want to check that you've processed the last data...

如果你想使用空行来确定新行的开始,它看起来像这样(修改第二个解决方案):

cat mydatafile.txt | while read foo; do
  if [ -z "$foo" ]
  then
    echo $row
    # process the data
    row=''
  else
    row="$row $foo"
  fi
done
# Here you NEED to process the last row unless the file ended in a blank line

这更适合带有自定义记录分隔符的 awk:

awk -v RS='\n\n' 'NF{printf "row=[%s]\n", [=10=]}' file
row=[name=...
phone=...
address=..]
row=[name=...
phone=..
address=...]
row=[name=...
phone=...
address=...]

-v RS='\n\n' 将记录分隔符设置为 2 个新行,然后 [=12=] 为您提供一个块的所有数据。

Working Demo

#!/bin/bash

i=1
str=""
while read row
do
    if (($i % 4 == 0 ))
    then
        echo $str
        # process $str
        str=""
    else
        str="$str\n$row"
    fi
    i=$(($i+1))
done < "mydatafile.txt"