我想在一行文字的末尾匹配一个可选标签。
示例输入文字:
The quick brown fox jumps over the lazy dog {tag}
我希望在花括号中匹配该部分,并创建一个对它的反向引用。
我的正则表达式如下:
^.*(\{\w+\})?
(有点简化,我也在标签之前匹配部分):
它匹配ok行(有和没有标记)但不创建对标记的反向引用。
如果我删除'?'性格,所以正则表达式是:
^.*(\{\w+\})
它会创建对标记的反向引用,但不会匹配没有标记的行。
我从http://www.regular-expressions.info/refadv.html了解到,可选运算符不会影响反向引用:
圆括号将它们之间的正则表达式组合在一起。它们捕获与其中可以在后向引用中重用的正则表达式匹配的文本,并且它们允许您将正则表达式运算符应用于整个分组的正则表达式。
但一定是误解了什么。
如何使标记部分可选并在存在时创建反向引用?
答案 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] + "]");
}
[]
[tag]
[]
[dog]