awk 重复 {n} 不起作用

For*_*ner 18 awk regular-expression

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

 awk '/^.{4}$/' test_data
Run Code Online (Sandbox Code Playgroud)

上面的代码没有打印出来。如何修复它以便我可以使用重复符号?我知道像awk '/^....$/' test_dataawk 'length ==3 ' test_data

Sté*_*las 20

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

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

所以一些实现选择不这样做。您会发现/bin/awk/bin/nawk/bin/egrep在 Solaris 上仍然不尊重它(您需要使用/usr/xpg4/bin/awk/usr/xpg4/bin/grep -E)。同为awknawk在FreeBSD(基于awk由Brian Kernighan的维护(在kawk))。

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

请注意,该运算符只是语法糖。例如,.{3,5}总是可以写....?.?的(尽管当然{3,5}更易读,而等效的(foo.{5,9}bar){123,456}会更糟)。


ste*_*ver 20

根据The GNU Awk User's Guide: Feature History,在 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}$/'
Run Code Online (Sandbox Code Playgroud)

或者

awk --posix '/^.{4}$/'
Run Code Online (Sandbox Code Playgroud)

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

POSIXLY_CORRECT=anything awk '/^.{4}$/'
Run Code Online (Sandbox Code Playgroud)

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

  • 最好使用`POSIXLY_CORRECT=anything awk '/^.{4}/'`,因为这使得代码可移植(`--posix` 或 `--re-interval` 会在其他 `awk` 实现中导致错误) . (4认同)

ter*_*don 6

这在 GNU awk(gawk) 中按预期工作:

$ printf 'abcd\nabc\nabcde\n' | gawk '/^.{4}$/'
abcd
Run Code Online (Sandbox Code Playgroud)

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

$ printf 'abcd\nabc\nabcde\n' | mawk '/^.{4}$/'
$ ## prints nothing
Run Code Online (Sandbox Code Playgroud)

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

$ printf 'abcd\nabc\nabcde\n' | grep '^.{4}$'
$
Run Code Online (Sandbox Code Playgroud)

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

$ printf 'abcd\nabc\nabcde\n' | grep -E '^.{4}$'
abcd
Run Code Online (Sandbox Code Playgroud)

我不知道mawkPOSIX使用哪种正则表达式awk,但我猜是 BRE. 根据Stéphane 的回答,他们使用旧版本的 ERE 。在任何情况下,要么您显然使用的awk是未实现 ERE的版本,要么您的输入实际上没有任何包含 4 个字符的行。例如,这可能是由于您看不到的空白或 unicode 字形造成的。