正则表达式组如何在条件内行为?

时间:2015-07-06 21:37:12

标签: regex conditional regex-lookarounds

我正在使用正则表达式条件(.net regex)。

假设这是我的字符串eat, drink, run

我想知道这个正则表达式

(eat)

在第1组中存储“eat”,用括号括起来,这个

(?:eat)

不会将匹配存储在任何组中,因为括号内有“?:”

然后,为什么这个条件正则表达式不起作用?

(eat)(?(1)a)

显示一条消息,说明组1中没有存储任何内容,是不是(吃)正确存储为一组?

为什么这个有条件的正则表达式有用呢?

(^)?eat(?(1)a)

返回“eat”存储在组1中,不应该认为要存储在组中的匹配必须用括号括起来吗?

请尝试在很多网站上找到解释,我在这个.NET正则表达式页面中测试这些正则表达式http://derekslager.com/blog/posts/2007/09/a-better-dotnet-regular-expression-tester.ashx

2 个答案:

答案 0 :(得分:1)

您似乎误解了conditionals in regex的概念。

  

特殊构造(?ifthen|else)允许您创建条件正则表达式。如果 if 部分的计算结果为true,那么正则表达式引擎将尝试匹配then部分。否则,将尝试使用 else 部分。   ... 您可以在 if 部分查看到目前为止捕获组是否参与了比赛。将捕获组的编号放在括号内,并将其用作if部分。

来自MSDN Details of Regular Expression Behavior

  

条件评估:(?(expression)yes|no)(?(name)yes|no),其中expression是要匹配的子表达式,name是捕获组的名称,yes是匹配的字符串如果匹配expressionname是有效的非空捕获组,则no是要匹配的子表达式{{1} }未匹配或expression不是有效的非空捕获组。

记住这些信息,很容易解释你的模式行为。

  

为什么这个条件正则表达式不起作用?

name将无效,因为正则表达式引擎找到(eat)(?(1)a),将其放入捕获组(进入堆栈#1)并遇到条件语句。它检查第1组是否参加了比赛(由于eat)。是的,它确实。然后,引擎会在(?(1)...)之后的条件(if)中查找a部分。没有eat,因此整场比赛失败

  

为什么这个有条件的正则表达式有用呢?

a中,您将一个捕获组放在字符串锚点的开头,该字符串锚点与由于(^)?eat(?(1)a)而未参与匹配的空字符串匹配,因此,?语句为寻找(?(1)...)部分 - 缺少(=空字符串会做)。换句话说,条件语句的计算结果为 false ,并且从未执行else之后的a搜索。因此,有一个匹配。作为experiment,您可以从正则表达式中移除eat:没有匹配项,因为没有? ,第一个捕获的组参加比赛,条件评估为 true

如果您需要将第一个捕获组评估强制为true并仍然将其作为可选项,则需要使用原子组(like this?来强制使用.NET正则表达式引擎将第一个捕获组视为有效的非空捕获组

答案 1 :(得分:0)

对于Dot-Net样式,请使用(?>(^)?)eat(?(1)a)
对于Perl样式,请使用(?>(^)?)eat(?(1)a)(^)?+eat(?(1)a)

这会强制引擎匹配BOS(如果是这种情况)
即使它是可选的。

如果没有占有地使用,引擎将选择来匹配(^)?
如果必须在尝试满足条件(?(1)a)时,如果不是 可能的任何其他方式。