awk 重复 {n} 不起作用

awk 重复 {n} 不起作用

我试图使用重复符号 {n} 打印这些行,但它不起作用。为了。例如我想打印长度为 4 个字符的所有行

 awk '/^.{4}$/' test_data

上面的代码没有打印该内容。如何修复它以便我可以使用重复符号?我知道像awk '/^....$/' test_dataand 这样的替代方案awk 'length ==3 ' test_data

答案1

根据GNU Awk 用户指南:功能历史,在 3.0 版本中添加了对正则表达式范围运算符的支持,但最初需要显式命令行选项

新的命令行选项:

  • 新的命令行选项:
    • --lint-old 选项用于警告原始版本 7 Unix 版本的 awk 中不可用的构造(请参阅 V7/SVR3.1)。
    • BWK awk 中的 -m 选项。 (Brian 当时还在贝尔实验室。)后来这句话从他的 awk 和 gawk 中删除了。
    • --re-interval 选项用于在正则表达式中提供间隔表达式(请参阅正则表达式运算符)。
    • 添加了 --traditional 选项作为 --compat 的更好名称(请参阅选项)。

gawk4.0中,

区间表达式成为默认正则表达式的一部分

由于您使用的是gawk3.x,因此您需要使用

awk --re-interval '/^.{4}$/'

或者

awk --posix '/^.{4}$/'

或者(感谢@StéphaneChazelas)如果您想要一个可移植的解决方案,请使用

POSIXLY_CORRECT=anything awk '/^.{4}$/'

(因为--posix--re-interval会在其他实现中导致错误awk)。

答案2

ERE(扩展正则表达式awk如or使用的egrep)最初没有{x,y}。它首先在 BRE 中引入(由grepor使用sed),但其\{x,y\}语法不会破坏向后可移植性。

但是当它使用该语法添加到 ERE 时{x,y},它确实破坏了向后可移植性,因为foo{2}RE 匹配了之前不同的东西。

所以一些实现选择不这样做。您会发现/bin/awk,/bin/nawk并且/bin/egrep在 Solaris 上仍然不遵守它(您需要使用/usr/xpg4/bin/awk/usr/xpg4/bin/grep -E)。对于 FreeBSDawk来说是一样的nawk(基于awk由 Brian Kernighan维护kawk))。

对于 GNUawk,直到最近(版本 4.0),您必须使用 来调用POSIXLY_CORRECT=anything awk '/^.{4}$/'它才能兑现它。mawk仍然不尊重它

请注意,该运算符只是语法糖。.{3,5}总是可以写成....?.?example (当然,这样{3,5}更易​​读,而相当于 的情况(foo.{5,9}bar){123,456}会更糟)。

答案3

awk这与 GNU (gawk)的预期一致:

$ printf 'abcd\nabc\nabcde\n' | gawk '/^.{4}$/'
abcd

但是失败了,mawk它更接近 POSIX awk,并且 AFAIK,它是 Ubuntu 系统上的默认值:

$ printf 'abcd\nabc\nabcde\n' | mawk '/^.{4}$/'
$ ## prints nothing

因此,一个简单的解决方案是使用gawk而不是awk.该{n}表示法不是 POSIX BRE(基本正则表达式)语法的一部分。这就是为什么grep这里也失败的原因:

$ printf 'abcd\nabc\nabcde\n' | grep '^.{4}$'
$

然而,它是 ERE(扩展正则表达式)的一部分:

$ printf 'abcd\nabc\nabcde\n' | grep -E '^.{4}$'
abcd

mawk我不知道or POSIX使用哪种正则表达式风格awk,但我猜它是 BRE。他们使用旧版本的 ERE 根据史蒂芬的回答。无论如何,要么您显然使用的版本awk不实现 ERE,要么您的输入实际上没有任何包含 4 个字符的行。例如,由于您看不到的空白或 unicode 字形,可能会发生这种情况。

相关内容