【问题标题】:expected behavior of posix extended regex: (()|abc)xyzposix 扩展正则表达式的预期行为: (()|abc)xyz
【发布时间】:2009-09-17 00:43:35
【问题描述】:

在我的 OS X 10.5.8 机器上,使用 regcomp 和 regexec C 函数来匹配扩展的正则表达式“(()|abc)xyz”,我找到了字符串“abcxyz”的匹配项,但仅从偏移量 3 到偏移量 6。我的期望是匹配整个字符串,并且我会看到字符串的初始“abc”部分的子匹配。

当我在同一台机器上使用 awk 尝试相同的模式和文本时,它会显示整个字符串的匹配项。

我希望我对正则表达式的有限经验可能是问题所在。有人可以解释发生了什么吗?我的正则表达式有效吗?如果是这样,为什么它不匹配整个字符串?

我知道“((abc){0,1})xyz”可以用作替代方案,但是感兴趣的模式是从另一种模式格式自动生成的,消除“()”的实例是额外的工作如果可能,我想避免。

作为参考,我传递给 regcomp 的标志仅包含 REG_EXTENDED。我将一组空标志 (0) 传递给 regexec。

【问题讨论】:

  • 出于兴趣,你可以试试“(abc|())xyz”吗?
  • 使用(abc)? 会起作用,而且比你使用的要短。
  • 出于对这是否真的是由于 UB 或错误引起的兴趣,您可以尝试 ((c)|abc)xyz 并查看它匹配的范围吗?我怀疑乔纳森这次是对的,但我从 OSX 了解到,首先考虑实现存在错误的可能性通常是明智的......

标签: c regex posix


【解决方案1】:

POSIX 标准说:

9.4.3 ERE 特殊字符

ERE 特殊字符在某些上下文中具有特殊属性。在这些上下文之外,或者当前面有 <backslash> 时,这样的字符应该是与特殊字符本身匹配的 ERE。扩展的正则表达式特殊字符及其特殊含义的上下文如下:

.[\(

<period>、<left-square-bracket>、<backslash> 和 <left-parenthesis> 应该是特殊的,除非在括号表达式中使用(请参阅 RE 括号表达式)。在括号表达式之外,<left-parenthesis> 紧跟 <right-parenthesis> 会产生未定义的结果。

您所看到的是调用未定义行为的结果 - 任何事情都会发生。

如果您想要可靠、可移植的结果,则必须消除空的“()”符号。

【讨论】:

  • 是的,我认为最好的选择是避免使用()。尽管我的系统确实在其re_format(7) 手册页中定义了我想要的行为,但要做的事情是坚持使用 POSIX。感谢您挖掘参考。
【解决方案2】:

如果您遍历所有匹配项,但没有同时获得 [3,6) 和 [0,6),则存在错误。至于返回匹配项的顺序,我不确定 posix 的要求。

【讨论】:

  • 遍历所有匹配得到 [3,6)、[3,3) 和 [3,3)。第一个是根据 regexec 手册页对整个正则表达式的匹配。
【解决方案3】:

试试(abc|())xyz - 我敢打赌它会在两个地方产生相同的结果。我只能假设 C 版本正在尝试尽可能匹配 xyz,如果失败,它会尽可能匹配 abcxyz(但是,如您所见,它不会失败,所以我们永远不会打扰“abc”部分),而awk 必须使用它自己的正则表达式引擎来执行您期望的方式。

您的正则表达式有效。我认为问题是 a) POSIX 不太清楚正则表达式应该如何工作,或者 b) awk 没有使用 100% 符合 POSIX 的正则表达式(可能是因为 OS X 附带了更原始的版本awk)。无论是哪个问题,都可能是因为这有点极端,大多数人不会那样编写正则表达式。

【讨论】:

  • 有趣的想法!我尝试使用“(abc |())xyz”,它按照我的预期进行了匹配;返回整个正则表达式的 [0,6) 和子匹配的 [0,3)。据我了解标准,它应该始终使用所有候选人中最长的匹配。所以如果你对正在发生的事情是正确的,我认为这是一个错误。
  • 这听起来像一个错误。我所能做的就是尝试解释它,除非我们窥视 glibc 的实现,我不想这样做,因为我相当有信心根据意外的输出知道其中发生了什么。也许您应该向 glibc 作者提交错误报告(或在另一台装有 GCC 的计算机上对其进行测试,以查看它是否可能只是 Apple 或旧版本的 glibc 问题)
  • 这不是错误 - 它是以未定义的方式表现的未定义行为。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-04
  • 1970-01-01
相关资源
最近更新 更多