正则表达式 - 积极前瞻在某些情况下不起作用

时间:2012-07-26 20:28:03

标签: c# regex

我正在遍历一系列C#关键字,并为每个关键字应用正则表达式。 (我正在研究语法高亮。)

我只想匹配:

  • 关键字是 OR 行之前的第一个单词 空格,句号或左括号

  • 关键字后面的字符是空格,句号或开放 括号。

以下是我提出的建议:

    foreach (string keyword in keyWords)
    {
        regex = new Regex(@"(?<=[\s\.(])" + keyword + @"(?=[\s\.(])");
        foreach (Match match in regex.Matches(code))
        {
            code = code.Replace(match.Value, "<span class='keyword'>" + match.Value + "</span>");
        }
    }

因此,在以下文字的情况下:

“foreach(ss中的字符串s){}”

单词“foreach”匹配,但关键字“in”嵌套int中单词“string”匹配 - 但这并不好,因为前后的字符与标准不匹配。

有趣的是,在以下文字的情况下:

“xforeachx(ss中的字符串s){}”

“foreach”这个词不匹配。

那么为什么单词“string”中的“in”与第二个例子中的“foreach”相匹配?我错过了什么?

谢谢!

1 个答案:

答案 0 :(得分:1)

以下是我在评论中引用的一个非常简单的演示:

StringBuilder sb = new StringBuilder();
sb.AppendLine("using System;");
sb.AppendLine();
sb.AppendLine("namespace Foo.Bar");
sb.AppendLine("{");
sb.AppendLine("\tpublic class Baz");
sb.AppendLine("\t{");
sb.AppendLine("\t\tpublic static void Main()");
sb.AppendLine("\t\t{");
sb.AppendLine("\t\t\tString[] a = new[]{\"foo\",\"bar\",\"baz\"};");
sb.AppendLine("\t\t\tforeach (var b in a) Console.WriteLine(b);");
sb.AppendLine("\t\t}");
sb.AppendLine("\t}");
sb.AppendLine("}");

Console.Write(sb.ToString());
Console.WriteLine();

String[] keywords = new String[]{
  "using", "namespace", "for", "if", "else", "foreach"
};
String code = sb.ToString();
foreach (String keyword in keywords){
  String pattern = @"(?<=^|[\s\.\(])(" + Regex.Escape(keyword) + @")(?=[\s\.\)])";
  String replacement = "<span class='keyword'>$1</span>";
  code = Regex.Replace(code, pattern, replacement);
}
Console.WriteLine(code);

导致:

<span class='keyword'>using</span> System;

<span class='keyword'>namespace</span> Foo.Bar
{
  public class Baz
  {
    public static void Main()
    {
      String[] a = new[]{"foo","bar","baz"};
      <span class='keyword'>foreach</span> (var b in a) Console.WriteLine(b);
    }
  }
}

想想你在追求什么。我使用静态正则表达式方法,但你可以根据自己的喜好重构它。我想指出的一些事情:

  • 我强烈建议您在正在使用自己构建的正则表达式语句中插入值时使用Regex.Escape。即使关键字只是字母,以后的某些更改也可能会破坏它。比抱歉更安全。
  • 如果您要使用Regex查找关键字,也可以使用它来替换它。这样可以确保如果找到“for”(并且是关键字)那个 for的实例(替换为look(后面)验证而不是字符串中的“for”) (也许他们有一个名为foreshadow的变量 - 谁知道。
  • 我稍微修改了你的后视以包含^|,这意味着匹配一行的开头或在课程中找到的内容。
  • 我还稍微修改了你的模式以包含一个捕获组,以便替换有一些东西可以找到。