根据格式

时间:2016-01-31 18:07:05

标签: linux unix awk sed grep

我有一个内容为:

的文件
  

您好欢迎
!块开始
线路1
线路2
!块开始
线路1
线路2
线路3!块起始线路1线路2线路3线路线路1线路2线路3线路3线路4路线5
线路1
线路2
线路3
线路4

现在,一切都以“!Chunk Start”开始,然后在下一个“!Chunk Start”之前是一个块,即“之间的线!开始“,做一大块。我需要在一行中获取每个块的内容。即:

  

1号线2号线1号线2号线3号线1号线1号线2号线3号线1号线2号线3号线4号线5号线1号线2号线3号线4号线

我已经这样做了,但我认为应该有更好的方法。我这样做的方式是:

grep -A100 "! Chunk Start" file.txt

其余的逻辑是连接线。但是这个 A100 是我担心的。如果一个块中有超过100行,这将失败。 我可能需要用awk / sed来做这件事。请建议。

3 个答案:

答案 0 :(得分:5)

您可以使用GNU AWK(gawk)。它有powerful regexp form of the record separator RS的GNU扩展,可以将输入除以! Chunk Start。然后可以将“块”的每一行作为字段处理。标准AWK对字段数有限制(99或其他?),但gawk supports up to MAX_LONG fields。大量的字段可以解决您对每个块的100多个输入行的担忧。

$ gawk 'BEGIN{RS="! Chunk Start\n";FS="\n"}NR>1{$1=$1;print}' infile.txt

AWK(和GNU AWK)的工作原理是将输入分成记录,然后将每个记录分成字段。在这里,我们根据字符串RS划分记录(记录分隔符! Chunk Start),然后根据换行符FS将每个记录划分为字段(字段分隔符\n)。您还可以指定自定义输出记录分隔符ORS和自定义输出字段分隔符OFS,但在这种情况下我们想要的是默认值(ORS="\n"OFS=" ")。

分成记录时,第一个! Chunk Start之前的部分将被视为记录。我们使用NR>1忽略了这一点。我已经解释了你的问题规范

  

一切都以“!Chunk Start”开头,然后在下一个“!Chunk Start”之前是一块

表示一旦看到! Chunk Start,输入结束之前的所有内容都属于至少一些块

神秘的$1=$1强制gawk重新处理输入行$0,使用输入格式(FS)对其进行解析,消耗换行符。 print使用输出格式(OFSORS)打印此重新处理的行。

编辑:上面的版本在每行末尾打印空格。感谢@EdMorton指出默认字段分隔符FS空格(包括换行符)上分开,因此FS应保持不变:

$ gawk 'BEGIN{RS="! Chunk Start\n"}NR>1{$1=$1;print}' infile.txt

答案 1 :(得分:3)

这可能适合你(GNU sed):

sed '0,/^! Chunk Start/d;:a;$!N;/! Chunk Start/!s/\n/ /;ta;P;d' file

删除并包含包含! Chunk Start的第一行。收集用空格替换换行符的行。当找到下一个匹配项时,打印第一行,删除模式空间并重复。

答案 2 :(得分:3)

好悲伤。只需使用awk:

$ awk -v RS='! Chunk Start' '{$1=$1}NR>1' file
Line 1 Line2
Line 1 Line 2 Line 3
Line 1 Line 2 Line 3 Line 1 Line 2 Line 3 Line 4 Line 5 Line 1 Line 2 Line 3 Line 4

以上使用GNU awk进行多字符RS。