我怎样才能使这个正则表达式忽略大括号前面没有\

时间:2011-07-09 02:42:59

标签: .net regex

var r = new Regex(@"PW\[(?<name>.*)\]");

此正则表达式应与[]之间的名称匹配。但是,如何使正则表达式忽略以\为前缀的大括号?我缺乏甚至谷歌的术语。

也就是说,我需要它来查找名称等于'inuyasha'的[inuyasha],并将[inuyasha\]]与name = inuyasha\]匹配。

有意义吗?

校正

最后一场比赛应为inuyasha]。额外的\是一个错字。

3 个答案:

答案 0 :(得分:2)

你所寻找的术语是“负面的背后隐藏”。请注意,每个正则表达式都不支持此功能。它至少存在于Perl和Java中。

答案 1 :(得分:2)

你不能让正则表达式忽略任何东西 - 而不是你所说的方式。你所描述的是一个三步过程。首先,通过查找封闭的方括号找到名称,同时允许名称中的转义括号:

@"\[(?<name>(?:[^\\\[\]]|\\.)*)\]"

交替的第一部分[^\\\[\]]是一个否定的字符类,它匹配除反斜杠或方括号之外的任何一个字符。第二部分\\.匹配反斜杠后跟任何一个字符。第二个角色是什么并不重要;我们需要知道的是,它被反斜杠所逃脱。

第二步是通过捕获组提取名称:

string rawName = m.Groups["name"].Value;

...第三步是删除任何转义的反斜杠:

string name = Regex.Replace(rawName, @"\\(.)", "$1");

把这些全部放在一起,我们有

string test = @"find [inuyasha] or [\[inuyasha] or [inuyasha\]] or [inu\\yasha].";
Regex reg = new Regex(@"\[(?<name>(?:[^][\\]|\\.)*)\]");
foreach (Match m in reg.Matches(test))
{
  string rawName = m.Groups["name"].Value;
  string name = Regex.Replace(rawName, @"\\(.)", "$1");
  Console.WriteLine(name);
}

输出:

inuyasha
[inuyasha
inuyasha]
inu\yasha

注意主正则表达式中缩短的字符类:[^][\\]。如果类中的第一个字符(或否定^之后的第一个字符)是右方括号(]),则将其视为文字字符,而不是字符类的结尾。左方括号([)始终被视为文字字符,除非它在集合减法表达式中使用(例如[a-z-[aeiou]],用于小写辅音)。此信息特定于.NET正则表达式风格;其他口味有自己的规则。

答案 2 :(得分:1)

如果你知道在真正的结束括号之前可能只有一个这样的\],你可以使用这样的正则表达式:

PW\[(?<name>.*?(\\\])?)\]

如果可能还有更多,您可以将零或一更改为零或更多

PW\[(?<name>.*?(\\\])*)\]

对于像“one [two\]] three [four\]\]] five”这样的字符串,后者会产生这些匹配:

two\]
four\]\]

然后将“替换(”\“”,“]”)移除逃逸将是一件容易的事。

尝试使用lookbehind,但无法让它放弃\。如果您只匹配],就像(?<=\\)\]这样的模式一样,很棒。只要你想在lookbehind之前捕获字符,lookbehind匹配的字符也将成为结果的一部分。正则表达式不会从捕获组的中间丢弃东西。您要么必须在第二步中处理捕获,要么捕获多个相邻的组并连接您实际需要的组。