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(string s in ss){}"

「foreach」という単語は一致しますが、「string」という単語にネストされたキーワード「in」も一致します。ただし、前後の文字が条件に一致しないため、これは適切ではありません。

興味深いことに、次のテキストの場合:

"xforeachx(string s in ss){}"

「foreach」という単語は一致しません。

では、なぜ「文字列」という単語の「in」は一致するのに、2番目の例の「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自分で構築していない正規表現ステートメントの途中に値を挿入する場合に使用することを強くお勧めします。キーワードが文字だけであることが判明した場合でも、後日変更を加えると、それが壊れる可能性があります。転ばぬ先の杖。
  • 正規表現を使用してキーワードを検索する場合は、正規表現を使用して置換します。これにより、"for" が見つかった (そしてキーワードであった) 場合、for のインスタンスが (look(ahead|behind) 検証を使用して) 置き換えられ、文字列内に見つかった迷子の "for" ではないことが保証れます (おそらく、名前の付いた変数がある可能性があります)。foreshadow - 知るか。
  • 後読みを少し変更して^|、行の先頭またはクラスで見つかったものと一致することを意味します。
  • また、パターンを少し変更してキャプチャ グループを含めるようにしたので、置換で何かを見つけることができました。
于 2012-07-26T21:01:07.020 に答える