【问题标题】:How to set a multicharacter record separator RS in GNU awk so it encompasses the new lines?如何在 GNU awk 中设置多字符记录分隔符 RS 使其包含新行?
【发布时间】:2020-11-18 09:40:23
【问题描述】:

我正在使用 GNU Awk 4.1.3。我要处理这个文件:

$$$$
1
1
$$$$
2
2
$$$$
3
3
$$$$
1
clave
2
$$$$
5
5
$$$$

当给定的块中包含文本“clave”时,打印“$$$$”和下一个“$$$$”之间的行块。也就是说,对于给定的示例,我想要这个输出:

1
clave
2

我的解决方案是将record separator RS 设置为字符串“$$$$”。因为是特殊字符,所以需要转义,所以最后变成RS='\\$\\$\\$\\$'

awk -v RS='\\$\\$\\$\\$' '/clave/' file

这样做的问题是结果在块之前和之后包含一个新行:

$ awk -v RS='\\$\\$\\$\\$' '/clave/' file

1
clave
2

这是因为“$$$$”的末尾和“1”之间有一个新行,“2”和下一个“$$$$”之间也有一个新行。

为了避免这种情况,我在记录分隔符的两端添加了新行,所以它变成了RS='<strong>\n</strong>\$\$\$\$<strong>\n</strong>'。效果很好:

$ awk -v RS='\n\\$\\$\\$\\$\n' '/clave/' file
#            ^^^           ^^
1
clave
2

但是,这变得相当复杂,我想知道在记录分隔符中包含新行是否会产生一些我不知道的副作用。

为此,我想知道:如何设置记录分隔符使其包含新行?我的方法是否有效,还是因为我的方法有一些缺点而应该选择其他选择?

【问题讨论】:

  • 一个很好的问题,很久之后才注意到你的存在@fedorqui
  • 非常感谢@anubhava,很高兴看到你们这些好人还在!
  • 所提出的方法有一些缺点。 (1) 您的第一条记录将包含$$$$ 行,如果您的文件不以换行符结尾,则最后一条记录可能$$$$ 结尾。 @anubhava 提出的解决方案有效。如果您想包含空行作为 RS,您甚至可以考虑将其转换为 \n*\$\$\$\$\n*
  • @kvantour 非常好,这就是我正在寻找的洞察力。我做了一些测试,但没有找到这个案例。非常感谢。
  • 请注意,当使用@anubhava 定义的RS 时,如果您的文件以RS 开头,那么您的第一条记录(FNR==1)将为空。

标签: regex awk


【解决方案1】:

你应该在 4 $s 之前和之后匹配换行符,因为那是真正的分隔符(在它自己的一行上的 4 个 $s 字符串),如果 4 @987654323 其他任何东西都可能失败@s 出现在您的数据中。 $s 的第一个字符串当然不会有换行符,它会匹配字符串开始指示符 (^),所以你需要使用:

$ awk -v RS='(^|\n)[$]{4}\n' '/clave/' file
1
clave
2

我发现 [$]\\$ 更容易阅读,YMMV。

【讨论】:

  • 非常好,非常感谢 Ed。时光荏苒,你始终是在 Awk 领域中获得更多光芒的人
【解决方案2】:

您在之前和之后都有一个换行符,因为在您的文件中 $$$$ 之前和之后都有一个换行符,并且通过将 RS 设置为 $$$$ 您将这些换行符保留在记录中。

更改您的 RS 以包含换行符或在之前开始和换行符或之后结束,以便记录将没有这些换行符:

awk -v RS='(^|\n)\\${4}(\n|$)' '/clave/' fike

1
clave
2

另请注意,您可以使用固定长度量词 \\${4} 而不是 \\$\\$\\$\\$

【讨论】:

  • 确实,如果您强制将\n[$][$][$][$]\n 设置为RS,则OP 的示例文件不会将第一行作为记录,如果文件不以换行符。这里提出的解决方案避免了这个问题。设置这个RS 的副作用是在大多数情况下,第一条记录是空的。
  • 如果$$$$ 出现在记录的中线,那将失败,例如foo$$$$bar.
  • 好吧,现在看起来very familiar :-)。最后不需要(\n|$),只需\n,因为文本文件总是以\n 结尾。
  • 啊,我刚刚注意到您的回答和++。当文件不以换行符结尾时,会留下(\n|$)
猜你喜欢
  • 1970-01-01
  • 2012-08-08
  • 1970-01-01
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
  • 2017-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多