带有可选部分的正则表达式不会创建反向引用

时间:2010-06-09 18:44:32

标签: c# .net regex capturing-group

我想在一行文字的末尾匹配一个可选标签。

示例输入文字:

The quick brown fox jumps over the lazy dog {tag}

我希望在花括号中匹配该部分,并创建一个对它的反向引用。

我的正则表达式如下:

^.*(\{\w+\})?

(有点简化,我也在标签之前匹配部分):

它匹配ok行(有和没有标记)但不创建对标记的反向引用。

如果我删除'?'性格,所以正则表达式是:

^.*(\{\w+\})

它会创建对标记的反向引用,但不会匹配没有标记的行。

我从http://www.regular-expressions.info/refadv.html了解到,可选运算符不会影响反向引用:

  

圆括号将它们之间的正则表达式组合在一起。它们捕获与其中可以在后向引用中重用的正则表达式匹配的文本,并且它们允许您将正则表达式运算符应用于整个分组的正则表达式。

但一定是误解了什么。

如何使标记部分可选并在存在时创建反向引用?

5 个答案:

答案 0 :(得分:3)

这不是一个反向引用问题,问题是只需阅读匹配.*的文本即可满足正则表达式。它不觉得有必要继续阅读以阅读可选的结束标记。如果您真正阅读到最后一行,最简单的解决方案是附加$(美元符号)以强制正则表达式匹配整行。

修改

顺便说一句,由于你说它与其他东西相匹配,所以我没有把你的reg-ex字面上看,但是要清楚.*将消耗整行。您需要[^{]*之类的东西来防止标记被吞噬。我猜这对你来说不是问题。

答案 1 :(得分:2)

除了其他人解释的内容之外,你可能想让.*“懒惰”:

^.*?(\{\w+\})?

答案 2 :(得分:1)

正如David Gladfelter所说,实际问题是当你把它作为可选项时,它与不匹配;但是,他提议的修复不起作用编辑1:你需要使用他在编辑中放置的东西(在写这篇文章的时候写完)。问题是量词(*+?{n,m}贪婪:它们总是尽可能匹配。因此,当您编写^.*(\{\w+\})?时,.*将始终与整行匹配,因为空匹配满足可选组。另请注意,虽然?是贪婪的,但第一次贪婪(.*)优先。如果您只允许在该可选组周围使用大括号,那么您可以通过明确说明来解决您的问题:^[^\{]*(\{\w+\})?。这样,第一个块将匹配第一个花括号的所有内容,然后(因为?贪婪)匹配卷曲括号的单词,如果可以的话。

通常,解决此问题的另一种方法是通过附加?*?,{使量词 lazy (或非贪婪,最小等) {1}},+???。但是,这对您没有帮助:相反,如果您执行{n,m}?,则惰性^.*?(\{\w+\})?将尝试匹配零个字符,成功,然后可选组将不匹配。尽管它在这里不起作用,但它仍然是您工具箱中的一个有用工具。 编辑1:另请注意,这些在所有正则表达式引擎中都不可用,尽管它们在C#中可用。

答案 3 :(得分:1)

谢谢你们。我使用了答案的组合,非贪婪的修饰符和行尾匹配,这似乎可以解决问题,所以现在正则表达式是:

^.*?(\{\w+\})?$ 

我不想在匹配的第一部分使用[^ {] *,因为此处可能会出现非标记花括号,但标记始终位于该行的末尾。

感谢您的回答,他们都很有帮助。

答案 4 :(得分:0)

如果您只对标记感兴趣,并且不关心字符串的其余部分,那么只需将标记与此正则表达式(see it on rubular.com)匹配,即可让您的生活更轻松:

\{(\w+)\}$

也就是说,您尝试匹配字符串末尾的某些{word}。如果它不存在,那么太糟糕了,没有匹配。不需要?修饰符或不情愿的.*以及所有这些内容。

在C#中,您甚至可能想要使用RegexOptions.RightToLeft,因为您无论如何都要尝试匹配后缀,所以可能是这样的:

string[] lines = {
  "The quick brown fox jumps over the lazy dog",
  "The quick brown fox jumps over the lazy dog {tag}",
  "The quick brown fox jumps over the {lazy} dog",
  "The quick brown fox jumps over the {lazy} {dog}",
};

Regex r = new Regex(@"\{(\w+)\}$", RegexOptions.RightToLeft);

foreach (string line in lines) {
  Console.WriteLine("[" + r.Match(line).Groups[1] + "]");
}

打印(as seen on ideone.com):

[]
[tag]
[]
[dog]