1

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

输入文本示例:

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

我想匹配花括号中的部分并创建对它的反向引用。

我的正则表达式如下所示:

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

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

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

如果我删除“?” 字符,所以正则表达式是:

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

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

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

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

但一定是误会了什么。

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

4

5 回答 5

3

这不是反向引用问题,问题在于仅通过读取匹配的文本就满足了正则表达式.*。没有必要继续阅读以阅读可选的结束标签。如果您真正阅读到行尾,最简单的解决方案是附加一个$(美元符号)以强制正则表达式匹配整行。

编辑

顺便说一句,我没有从字面上理解你的正则表达式,因为你说它与其他东西匹配,但为了清楚起见.*会消耗整条线。你需要一些东西[^{]*来防止标签被吞下。我猜这对你来说不是问题。

于 2010-06-09T18:49:03.700 回答
2

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

^.*?(\{\w+\})?
于 2010-06-09T18:55:31.563 回答
1

正如 David Gladfelter 所说,实际问题是当您将其设为可选时,它不匹配;但是,他提出的修复方法行不通编辑 1:您需要使用他在编辑中添加的内容(在我写这篇文章时写的)。问题是量词 ( *, +, ?, {n,m}) 是贪婪的:它们总是尽可能匹配。因此,当您编写 时^.*(\{\w+\})?.*将始终匹配整行,因为空匹配满足可选组。还要注意,虽然?是贪心的,但第一个贪心 (of .*) 优先。如果您只允许在该可选组周围使用大括号,那么您可以通过明确说明来解决您的问题:^[^\{]*(\{\w+\})?. 这样,第一个块将匹配到第一个花括号的所有内容,然后(因为?贪心)匹配花括号中的单词(如果可以)。

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

于 2010-06-09T19:02:13.190 回答
1

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

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

我不想在比赛的第一部分使用 [^{]* ,因为这里可能会出现非标记花括号,但标记将始终位于行尾。

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

于 2010-06-09T19:40:58.180 回答
0

如果您只对标签感兴趣,而不关心字符串的其余部分,那么只需将标签与此正则表达式匹配(在 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] + "]");
}

这打印(如在 ideone.com 上看到的):

[]
[tag]
[]
[dog]
于 2010-06-11T09:08:51.200 回答