awk的split()函数是使用正则表达式还是精确字符串常量?

7
如果我们有ip=192.168.0.1,并调用split(ip, myArray, "."),那么myArray将包含位置1为"192",位置2为"168",位置3为"0",位置4为"1"。
我的问题是为什么awk没有将"."解释为"任意字符"正则表达式?
如果我想让awk将"."解释为"任意字符"正则表达式以进行匹配,我需要做什么?
这种行为在所有awk实现中都是一致的吗?

请问您能否在这里展示一下样例输入文件和期望输出结果? - RavinderSingh13
2个回答

20

这确实是 awk 的一个较为难懂的角落....

我在五年前也有同样的疑问。我将其提交为 bug 并与 gawk 的开发人员交谈,最终得到了清晰的解释。这是一个“特性”。

这里是工单链接:https://lists.gnu.org/archive/html/bug-gawk/2013-03/msg00009.html

split(str, array, magic)

关于 magic

  • 当你使用非空字符串(由""引用)"..."时,awk会检查字符串长度。如果它是单个字符,则将其用作字面字符串(称为分隔符)。但是如果长度超过了1,则将其视为动态正则表达式。

  • 当您使用静态正则表达式,即格式为 /.../ 的表达式时,无论表达式多长,它始终将被视为正则表达式。

也就是说:

"."  - literal "." (period)
"["  - literal "["
"{"  - literal "{"
".*" - regex
/./  - regex
/whatever/ -regex

如果你想让awk将.(period)作为正则表达式元字符处理,那么你应该使用split(foo,bar,/./)。但是,如果你按任意字符分割,可能会有空数组,如果这正是你想要的,请继续。


我实际上想在字面上的“.”(句号)处分割,但只是想知道为什么它有效(而awk没有将其视为正则表达式)。您的答案完全解释了我的困惑。您是否知道您所解释的内容适用于所有awk(如mawk,POSIX awk等)还是仅适用于gawk?(我看到您只提到了gwak) 编辑:查看链接的票证并发现其他awk也以这种方式工作,而不仅仅是gawk。 :) - Maytas Monsereenusorn
一切正确。话虽如此 - 由于split的第三个参数是一个正则表达式,因此您应该使用正则表达式而不是字符串作为分隔符,并且在正则表达式中指定字面量“.”的方法是将其放在括号表达式中,因此如果您只需正确编写代码为split(str,arr,/[.]/),那么这个问题甚至不会出现。 - Ed Morton

2

您应该使用/./来区分正则表达式和静态字符串,以便将每个字符用作定界符:

$ echo 192.168.0.1 | awk '{ split($0,a,/./); print a[1] }'
$               # nothing here, every char is a delimiter.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接