11

デフォルトでは、私の正規表現は私が望む貪欲な動作を示すと思いましたが、次のコードにはありません:

 Regex keywords = new Regex(@"in|int|into|internal|interface");
 var targets = keywords.ToString().Split('|');
 foreach (string t in targets)
    {
    Match match = keywords.Match(t);
    Console.WriteLine("Matched {0,-9} with {1}", t, match.Value);
    }

出力:

Matched in        with in
Matched int       with in
Matched into      with in
Matched internal  with in
Matched interface with in

単純にキーワードを長さの降順で並べ替えれば、この小さな例でも機能することがわかりましたが、

  • これが期待どおりに機能しない理由を理解したいのですが、
  • 私が取り組んでいる実際のプロジェクトでは、正規表現にさらに多くの単語が含まれており、それらをアルファベット順に保つことが重要です。

だから私の質問は、なぜこれが怠惰なのか、どうすれば修正できるのか?

4

3 に答える 3

12

怠惰と貪欲は量指定子 ( ?*+{min,max}) のみに適用されます。代替は常に順番に一致し、最初に一致する可能性があるものを試します。

于 2010-03-07T02:29:24.417 に答える
6

言葉を壊そうとしているようです。そのためには式全体が正しい必要がありますが、現在の式はそうではありません。代わりにこれを試してください..

new Regex(@"\b(in|int|into|internal|interface)\b");

「\b」は、単語の境界に一致することを示しており、ゼロ幅の一致です。これはロケールに依存する動作ですが、一般的にこれは空白と句読点を意味します。ゼロ幅の一致であるため、正規表現エンジンが単語境界を検出する原因となった文字は含まれません。

于 2010-03-07T03:28:05.173 に答える
3

RegularExpressions.infoによると、正規表現は熱心です。したがって、パイプされた式を通過すると、最初の完全な一致で停止します。

私のお勧めは、すべてのキーワードを配列またはリストに格納し、必要に応じて並べ替えられ、パイプ処理された式を生成することです。キーワード リストが変更されない限り、これも 1 回だけ行う必要があります。生成された式をある種のシングルトンに保存し、正規表現の実行時にそれを返すだけです。

于 2010-03-07T02:37:48.050 に答える