我有一个文件,内容如下:
Hi
welcome
! Chunk Start
Line 1
Line2
! Chunk Start
Line 1
Line 2
Line 3
! Chunk Start
Line 1
Line 2
Line 3
Line 1
Line 2
Line 3
Line 4
Line 5
Line 1
Line 2
Line 3
Line 4
现在,所有以 "!Chunk Start" 和下一个 "!Chunk Start" 开头的内容都是一个 block ,即 "!Chunk 之间的行开始”,做一个大块。我需要在一行中获取每个 block 的内容。即:
Line 1 Line 2
Line 1 Line2 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
我已经这样做了,但我认为应该有更好的方法。我这样做的方式是:
grep -A100 "!Chunk Start"file.txt
剩下的逻辑就是连接这些行。但是这个A100是我担心的。如果一个 block 中有超过 100 行,这将失败。 我可能需要用 awk/sed 来做这件事。请提出建议。
最佳答案
您可以使用 GNU AWK (gawk
)。它有一个 GNU 扩展 powerful regexp form of the record separator RS
将输入除以 ! block 开始
。然后可以将“ block ”的每一行作为一个字段进行处理。标准 AWK 对字段数有限制(99 或什么?),但是 gawk
supports up to MAX_LONG
fields .如此大量的字段应该可以解决您对每个 block 100 多行输入的担忧。
$ gawk 'BEGIN{RS="! Chunk Start\n";FS="\n"}NR>1{$1=$1;print}' infile.txt
AWK(和 GNU AWK)的工作原理是将输入分成记录,然后将每条记录分成字段。这里,我们是根据字符串来划分记录(记录分隔符
,然后将每条记录按换行符RS
)! Chunk Start\n
划分为字段(字段分隔符FS
)。您还可以指定自定义输出 记录分隔符ORS
和自定义输出 字段分隔符OFS
,但在这种情况下我们希望恰好是默认值(ORS="\n"
和 OFS=""
)。
分记录时,第一个之前的部分! Chunk Start
将被视为一条记录。我们使用 NR>1
忽略它。我已经解释了你的问题说明
everything beginning with "! Chunk Start" and before the next "! Chunk Start" is a chunk
表示一次!已看到 block 开始
,直到输入结束之前的所有其他内容都属于至少一些 block 。
神秘的$1=$1
强制gawk
重新处理输入行$0
,后者使用输入格式(FS
),消耗换行符。 print
使用输出格式(OFS
和 ORS
)打印此重新处理的行。
编辑:上面的版本在每行末尾打印空格。感谢@EdMorton 指出默认字段分隔符 FS
在 whitespace 上分隔(包括换行符),因此 FS
应该保持不变:
$ gawk 'BEGIN{RS="! Chunk Start\n"}NR>1{$1=$1;print}' infile.txt
关于linux - 根据格式从文件中批量提取行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35117348/