我有一个内容为:
的文件您好欢迎
!块开始
线路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来做这件事。请建议。
答案 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
使用输出格式(OFS
和ORS
)打印此重新处理的行。
编辑:上面的版本在每行末尾打印空格。感谢@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。