Apple awk,正则表达式中的等价类表达式

问题描述 投票:0回答:1

我偶然发现了 Apple 的 awk 关于等价类的奇怪行为,所以我试图了解正则表达式解析器的细节:

绳子 正则表达式
gsub(regexp, "_", string); print string
anything
[[=a]
awk:非终止字符类
][=ab
[[=a]]
_[=ab
anything
[[=a=]
awk:非终止字符类
][=ab
[[=a=]]
][=_b
][=ab
[[=ab]
][=a_
][=ab
[[=ab=]
][_a_
][=ab
[[=ab=]]
][=ab
][=ab(
[[=ab(=]
][_a__
][=ab(
[[=ab=](]
awk:语法错误

是否可以伪造一个多平台测试(BSD、Apple、GNU、POSIX)来确定正则表达式引擎是否已损坏,而不造成

awk
崩溃


旁白: 用于测试的示例代码(第一行):

awk 'BEGIN{
    string="anything"; regexp="[[=a]";
    gsub(regexp, "_", string); print string
}'
regex macos awk
1个回答
0
投票

源代码显示,当解析器在括号表达式中遇到

[.
[=
时,它会消耗[.
[=
之后的
一个字符
(可以是多字节)并检查匹配
.]
=]
:

  • 找到后,它会移动到这 2 个字符之后并返回到“内括号表达式”状态。
  • 当没有找到时,则不执行任何操作;解析器只是返回到“内括号表达式”状态。

此外(幸运的是),BSD 的解析器在

[:
[.
内时不会转换反斜杠转义序列;我们可以“利用”这个事实,并使用例如
\t
,这是在
[:
[.
内部使用的合法转义序列,来表征此特定实现:

# BSD awk (macOS and FreeBSD)
awk 'BEGIN { print match("\t", /[[=\t=]]/) }'
0

# GNU awk
awk 'BEGIN { print match("\t", /[[=\t=]]/) }'
1

# Solaris XPG4 awk
command -p awk 'BEGIN { print match("\t", /[[=\t=]]/) }'
1

[[=\t=]]
发生的情况是:

  1. [
    被消耗,解析器被置于 inside-bracket-expression 状态。
  2. [=
    被消耗,解析器获取下一个字符,即
    \
  3. 解析器在接下来的 2 个字符(即
    t
    =
    )处获取“峰值”,并将它们与
    =
     
    ]
    进行比较。由于它们不匹配,解析器返回到 inside-bracket-expression 状态,并且对之前的
    \
    (错误)不执行任何操作。
  4. t
    被消耗并添加括号表达式的字符列表。
  5. =
    被消耗了,我不知道为什么解析器不做任何事情?
  6. ]
    被消耗,解析器进入 outside-bracket-expression 状态。
  7. ]
    被消耗并连接到前面的括号表达式。

考虑到这些步骤,另一个可行的测试是:

# BSD awk (macOS and FreeBSD)
awk 'BEGIN { print match("t]", /[[=\t=]]/) }'
1

# GNU awk
awk 'BEGIN { print match("t]", /[[=\t=]]/) }'
0

# Solaris XPG4 awk
command -p awk 'BEGIN { print match("t]", /[[=\t=]]/) }'
0
© www.soinside.com 2019 - 2024. All rights reserved.