linux - 根据格式从文件中批量提取行

标签 linux unix awk sed grep

我有一个文件,内容如下:

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 使用输出格式(OFSORS)打印此重新处理的行。

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

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

关于linux - 根据格式从文件中批量提取行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35117348/

相关文章:

c - container_of() 宏中的赋值运算符是如何工作的

java - 在 Java 中重复 Unix 命令

count - 对列中的唯一值进行编号

linux - awk 脚本在特定行打印信息

linux - 为什么需要硬链接(hard link)和软链接(soft link)?

linux - 如何强制 UDP 数据的完整校验和?

python - 声音输出存在于声音输入中,即使在 Linux 中没有麦克风

linux - 在 Linux 中删除以特定字符串结尾的特定文件

c - 如何在 C 中对包含 "%"的字符串执行 strcmp?

linux - awk 列减去一个常量