0

次の正規表現を検討してください。

(?:([A-Z][0-9a-z]*)+?)

文字列「A1BaaC2d」に適用すると、「A1」、「Baa」、「C2d」の 3 つのグループが得られます。

ただし、開始文字列アンカーと終了文字列アンカー、つまり ^(?:([AZ][0-9a-z]*)+?)$ を適用すると、正しく機能しなくなります。これは参照の問題だと思います(したがって、非キャプチャでアトミックとして試した余分なグループ化です)。しかし、私はそれをうまく解決することはできません。グループを取得して、合計文字列に先頭または末尾の文字がないことを検証するにはどうすればよいですか?

参考までに、これは .net 正規表現です。

4

1 に答える 1

3

これを本質にまで絞り込みましょう:

([A-Z][0-9a-z]*)+

(結果に影響がなかったため、外側の非キャプチャグループを削除し、一時的?に数量化子から削除しました。)1つのキャプチャグループを持つ正規表現があります。そのグループ内の部分式は、数量詞のために少なくとも1回は一致する必要があり+ますが、数量詞はデフォルトで貪欲であるため、実際には入力と3回一致します。内訳は次のとおりです。

Match 1 = A1BaaC2d
Group 1 = C2d
Capture 1 = A1
Capture 2 = Baa
Capture 3 = C2d

(「グループ1」は、そのグループによってキャプチャされた最終的な値を指します。ほとんどの正規表現フレーバー/ツールでは、それが取得するすべての情報です。.NETは、すべての中間キャプチャも分割できるという点で独特です。)

ただし、貪欲でないバージョンの数量詞を使用しました+?

    ([A-Z][0-9a-z]*)+?

[A-Z][0-9a-z]*それでも少なくとも1回は一致(およびキャプチャ)する必要がありますが、何かが強制的に続行しない限り、すぐに停止します。何もしないので、それぞれが1つのキャプチャを含む3つの別々の一致を取得します。

Match 1 = A1
Group 1 = A1
Capture 1 = A1

Match 1 = Baa
Group 1 = Baa
Capture 1 = Baa

Match 1 = C2d
Group 1 = C2d
Capture 1 = C2d

次に、アンカーを追加しました。

^([A-Z][0-9a-z]*)+?$

これで、各一致は文字列の先頭で開始し、文字列の末尾で終了する必要があります。これを実現するために、正規表現エンジンはの貪欲さを無効にし、+?3つのキャプチャで1つの一致に戻ります。

Match 1 = A1BaaC2d
Group 1 = C2d
Capture 1 = A1
Capture 2 = Baa
Capture 3 = C2d

以下は、この出力を生成するために使用したコードの最終バージョンです。貪欲でない正規表現を実際に使用する必要はないことに注意してください。^([A-Z][0-9a-z]*)+$同様に機能します。

static void Main()
{
  string source = "A1BaaC2d";
  Regex r = new Regex(@"^([A-Z][0-9a-z]*)+?$");
  foreach (Match m in r.Matches(source))
  {
    int x = 1;
    Console.WriteLine(@"Match {0} = {1}", x++, m.Value);
    Console.WriteLine(@"Group 1 = {0}", m.Groups[1]);
    int y = 1;
    foreach (Capture c in m.Groups[1].Captures)
    {
      Console.WriteLine(@"Capture {0} = {1}", y++, c.Value);
    }
    Console.WriteLine();
  }
}
于 2013-02-15T03:27:36.987 に答える