2

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

我只想匹配,如果:

  • 关键字是该行的第一个单词前面的字符是空格、句点或左括号

  • 关键字后面的字符是空格、句点或左括号。

这是我想出的:

    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”嵌套在单词“string”匹配 - 但这不好,因为之前和之后的字符不匹配标准。

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

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

“foreach”这个词不匹配。

那么为什么“string”这个词中的“in”匹配,而第二个例子中的“foreach”却不匹配呢?我错过了什么?

谢谢!

4

1 回答 1

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(ahead|behind) 验证,而不是在字符串中找到杂散的“for”(也许它们有一个名为foreshadow - 谁知道。
  • 我稍微修改了您的后视功能,以包括^|匹配行首或在类中找到的内容。
  • 我还稍微修改了您的模式以包含一个捕获组,以便替换有一些东西可以定位。
于 2012-07-26T21:01:07.020 回答