意外的分裂行为

意外的分裂行为

我在这里阅读了有关 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>从 的前后被修剪exprsep变成<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行为:

  1. 如果FS是空字符串,行为未指定。
  2. 如果FS是一个单个字符:

    A。如果FS为 <space>,跳过前导和尾随 <blank> 和 <newline> 字符;字段应由一组或多组 <blank> 或 <newline> 字符分隔。

    b.否则,如果FS是任何其他字符 c,字段应由每次出现的 c 分隔

  3. 否则,字符串值FS应被视为扩展正则表达式。与扩展正则表达式匹配的序列的每次出现都应界定字段。

您的示例与 2.b 匹配。

即使明确提到FS,它与所有 awk 实现中使用的任何参数而不是它作为第三个参数的行为相同split,包括该参数是空格的情况。

行为不太可能改变,因为FS变量只是一个字符串(awk没有正则表达式对象,如javascriptor 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

相关内容