posix扩展正则表达式的预期行为:(()| abc)xyz

时间:2009-09-17 00:43:35

标签: c regex posix

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

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

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

我理解“((abc){0,1})xyz”可以作为替代,但感兴趣的模式是从另一种模式格式自动生成的,并且消除“()”的实例是额外的工作我想尽可能避免。

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

3 个答案:

答案 0 :(得分:2)

POSIX标准说:

  

9.4.3 ERE特殊字符

     

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

     

.[\(

     

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

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

如果您想获得可靠,便携的结果,则必须删除空的“()”符号。

答案 1 :(得分:0)

如果你遍历所有匹配,并且没有同时获得[3,6]和[0,6],那么就有一个错误。我不确定posix要求返回匹配的顺序。

答案 2 :(得分:0)

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

你的正则表达式是有效的。我认为问题是a)POSIX不是很清楚正则表达式应该如何工作,或者b)awk没有使用100%POSIX兼容的正则表达式(可能是因为OS X出现了更多原始版本awk)。无论遇到什么问题,都可能是因为这有点像边缘情况,大多数人都不会这样写正则表达式。