在他们引用的小组之后需要进行反向引用吗?

时间:2013-08-20 20:03:15

标签: c# .net regex backreference

在为this answer运行某些测试时,我注意到以下意外行为。这将删除第一个出现后<tag>的所有内容:

var input = "<text><text>extra<words><text><words><something>";
Regex.Replace(input, @"(<[^>]+>)(?<=\1.*\1)", "");
// <text>extra<words><something>

但这不会:

Regex.Replace(input, @"(?<=\1.*)(<[^>]+>)", "");
// <text><text>extra<words><text><words><something>

同样,这将删除<tag>之前发生的所有事件:

Regex.Replace(input, @"(<[^>]+>)(?=.*\1)", "");
// extra<text><words><something>

但这不会:

Regex.Replace(input, @"(?=\1.*\1)(<[^>]+>)", "");
// <text><text>extra<words><text><words><something>

所以这让我想到了......

在.NET正则表达式引擎中,在引用它的组后,是否需要在后出现反向引用?或者这些模式还有其他因素导致它们不起作用吗?

1 个答案:

答案 0 :(得分:4)

你的问题也让我思考了,所以我用RegexBuddy进行了一些测试,令我惊讶的是你说的第二个正则表达式(?<=\1.*)(<[^>]+>)实际上没有用,而其他人的工作方式与你完全一样说过。然后我在C#代码中尝试了相同的表达式 - 第二个 - ,但它不像你发生的那样工作。

这让我感到困惑,然后我注意到我的RegexBuddy版本可以追溯到2008年,所以.NET引擎的运行方式一定有一些变化,但这揭示了一个事实我虽然是理性的,但似乎2008年之前,在表达式的其余部分匹配后评估了lookbehinds。我觉得这种行为对于外观来说是有点可以接受的,因为你需要先匹配一些东西才能看到后面的东西。

然而,这些天的引擎似乎在遇到它们时会评估外观,我可以通过使用下面的表达式找到它,就像你的情况相反:

(?<=(\w))\1

正如您所看到的,我在正则表达式中捕获了一个单词字符并在其外部引用了它。我在字符串hello上对此进行了测试,并且在第二个l字符处按预期匹配,这证明在尝试匹配表达式的其余部分之前执行了lookbehind。

结论:是的,后引用需要在它引用的组之后出现,否则它将没有匹配语义。