我在这里阅读了有关 Awk 拆分行为的信息:
[...] 这FS论证分裂函数(请参阅字符串函数)应被解释为扩展正则表达式。这些可以是埃雷
~
标记或任意表达式,并且应以与or运算符 右侧相同的方式进行解释!~
。
和:
如果右侧操作数是除词法标记之外的任何表达式 埃雷,表达式的字符串值应解释为扩展正则表达式,包括上述转义约定。
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html#tag_20_06_13_04
但是我注意到以下代码出现了意外的结果:
BEGIN {
print split("te.st", q, ".")
}
我希望.
代表任何字符,并且结果为6
。然而我的所有测试都返回了2
。运行此代码会得到预期的结果6
:
BEGIN {
print split("te.st", q, /./)
}
测试用:
- 呆呆地
- 呆呆的——posix
- 莫克 1.3.4
- 莫克 1.3.3
- nawk(原始 awk)
我是否误解了文档或者这是一个错误?
答案1
这不是一个错误;而是一个错误。只是在试图对现有做法进行编纂时,标准还不够明确。
mawk(1) 手册更明确:
split(expr, A, sep)
工作原理如下:...
(2) If
sep = " "
(单个空格), then<SPACE>
从 的前后被修剪expr
,sep
变成<SPACE>
。 mawk 定义<SPACE>
为正则表达式/[ \t\n]+/
。否则sep
被视为正则表达式,除了长度为 1 的字符串忽略元字符外,例如,split(x, A, "*")
和split(x, A, /*/)
是相同的。
另外,GNU awk 手册来自当前来源:
split(s, a [, r [, seps] ])
...
分割的行为与如上所述的字段分割相同。特别是,如果
r
是单字符字符串,则该字符串充当分隔符,即使它恰好是正则表达式元字符。
这是susv4的描述标准:
通过将包含表达式的字符串分配给内置变量,可以使用扩展正则表达式来分隔字段FS,直接或作为使用该选项的结果
-F sepstring
。默认值FS变量应为单个<space>。下面介绍一下FS行为:
- 如果FS是空字符串,行为未指定。
如果FS是一个单个字符:
A。如果FS为 <space>,跳过前导和尾随 <blank> 和 <newline> 字符;字段应由一组或多组 <blank> 或 <newline> 字符分隔。
b.否则,如果FS是任何其他字符 c,字段应由每次出现的 c 分隔。
否则,字符串值FS应被视为扩展正则表达式。与扩展正则表达式匹配的序列的每次出现都应界定字段。
您的示例与 2.b 匹配。
即使明确提到FS
,它与所有 awk 实现中使用的任何参数而不是它作为第三个参数的行为相同split
,包括该参数是空格的情况。
行为不太可能改变,因为FS
变量只是一个字符串(awk
没有正则表达式对象,如javascript
or perl
;您不能将正则表达式分配给变量,如a=/./
or $a=qr/./
);它是split
函数(隐式或显式调用)确实按上述方式解释其参数。
此行为的起源可能是与“旧”awk 兼容,其中FS
(或 的第三个参数split
)始终被视为单个字符。示例(在 UNIX v7 上):
$ awk 'BEGIN{FS="."; print split("foo.bar.baz", a, "bar"); print a[2] }'
3
ar.
$ awk 'BEGIN{FS="."; print split("foo.bar.baz", a, /bar/); print a[2] }'
awk: syntax error near line 1
awk: illegal statement near line 1
Bus error - core dumped