web-dev-qa-db-ja.com

C#正規表現での貪欲な、貪欲でない、貪欲なマッチング

次の例ですべての一致を取得するにはどうすればよいですか。

// Only "abcd" is matched
MatchCollection greedyMatches = Regex.Matches("abcd", @"ab.*");

// Only "ab" is matched
MatchCollection lazyMatches   = Regex.Matches("abcd", @"ab.*?");

// How can I get all matches: "ab", "abc", "abcd"

PS:すべての試合を一般的な方法で行いたいのですが。上記の例は一例です。

21
Peter Lee

あなたは次のようなものを使うことができます:

MatchCollection nonGreedyMatches = Regex.Matches("abcd", @"(((ab)c)d)");

次に、ab、abc、abcdの3つの後方参照が必要です。

しかし、正直に言うと、この種の正規表現はあまり意味がありません。特に、大きくなると判読できなくなります。

編集:

MatchCollection nonGreedyMatches = Regex.Matches("abcd", @"ab.?");

ところでエラーが発生しました。これは、abおよびabc(読み取り:ab +任意の(オプション)文字にのみ一致します。

の遅延バージョン:

MatchCollection greedyMatches    = Regex.Matches("abcd", @"ab.*");

です:

MatchCollection nonGreedyMatches    = Regex.Matches("abcd", @"ab.*?");
19
Tseng

ソリューションが存在する場合、おそらくキャプチャグループとRightToLeftオプションが含まれます。

string s = @"abcd";
Regex r = new Regex(@"(?<=^(ab.*)).*?", RegexOptions.RightToLeft);
foreach (Match m in r.Matches(s))
{
  Console.WriteLine(m.Groups[1].Value);
}

出力:

abcd
abc
ab

「if」と言ったのは、単純なテストケースでは機能するが、このトリックが実際の問題に役立つことを保証できないからです。 RightToLeftモードは.NETのより革新的な機能の1つです。つまり、同等の機能を持つ別のフレーバーは考えられません。それに関する公式のドキュメントはまばらで(控えめに言えば)、これまでのところ、それを使用してオンラインで経験を共有している開発者は多くないようです。だからそれを試して何が起こるか見てください。

4
Alan Moore

1つの一致だけでは3つの異なる結果を得ることができません。

「ab」のみに一致させたい場合は、ab.?またはa.{1}(または他の多くのオプション)
「abc」のみと一致させたい場合は、ab.またはa.{2}(または他の多くのオプション)
「abcd」のみと一致させたい場合は、ab.*またはa.{3}(または他の多くのオプション)

1
Colin Hebert