7

誰でも説明できますか:

  1. 以下で使用されている2つのパターンが異なる結果をもたらすのはなぜですか?(以下に回答)
  2. 2番目の例でグループ数が1であるのに、グループ1の開始と終了が-1であると言うのはなぜですか?
 public void testGroups() throws Exception
 {
  String TEST_STRING = "After Yes is group 1 End";
  {
   Pattern p;
   Matcher m;
   String pattern="(?:Yes|No)(.*)End";
   p=Pattern.compile(pattern);
   m=p.matcher(TEST_STRING);
   boolean f=m.find();
   int count=m.groupCount();
   int start=m.start(1);
   int end=m.end(1);

   System.out.println("Pattern=" + pattern + "\t Found=" + f + " Group count=" + count + 
     " Start of group 1=" + start + " End of group 1=" + end );
  }

  {
   Pattern p;
   Matcher m;

   String pattern="(?:Yes)|(?:No)(.*)End";
   p=Pattern.compile(pattern);
   m=p.matcher(TEST_STRING);
   boolean f=m.find();
   int count=m.groupCount();
   int start=m.start(1);
   int end=m.end(1);

   System.out.println("Pattern=" + pattern + "\t Found=" + f + " Group count=" + count + 
     " Start of group 1=" + start + " End of group 1=" + end );
  }

 }

これにより、次の出力が得られます。

Pattern=(?:Yes|No)(.*)End  Found=true Group count=1 Start of group 1=9 End of group 1=21
Pattern=(?:Yes)|(?:No)(.*)End  Found=true Group count=1 Start of group 1=-1 End of group 1=-1
4

4 に答える 4

9
  1. 違いは、2番目のパターン"(?:Yes)|(?:No)(.*)End"では、連結(「XY」の「Xの後にY」)が選択(「X | Y」の「XまたはY」)よりも優先順位が高いことです。たとえば、乗算はより優先順位が高くなります。さらに、パターンはと同等です

    "(?:Yes)|(?:(?:No)(.*)End)"
    

    取得したいのは次のパターンです。

    "(?:(?:Yes)|(?:No))(.*)End"
    

    これにより、最初のパターンと同じ出力が得られます。

    テストでは、2番目のパターンのグループ1が(空の)範囲にあります[-1, -1[。これは、そのグループが一致しなかったためです(開始-1が含まれ、終了-1が除外され、ハーフオープン間隔が空になります)。

  2. キャプチャグループは、入力をキャプチャできるグループです。キャプチャする場合は、入力の一部のサブストリングと一致するとも言います。正規表現に選択肢が含まれている場合、すべてのキャプチャグループが実際に入力をキャプチャするわけではないため、正規表現が一致しても一致しないグループが存在する可能性があります。

  3. によって返されるグループカウントは、特定の入力で一致する可能性があるかどうかに関係なく、キャプチャグループMatcher.groupCount()のグループ化ブラケットをカウントすることによって純粋に取得されます。パターンには、キャプチャグループが1つだけあります。これはグループ1です。ドキュメントには次のように記載されています。(.*)

    (?:X)    X, as a non-capturing group
    

    説明します

    で始まるグループ(?は、テキストをキャプチャせず、グループの合計にカウントされない純粋な非キャプチャグループ、または名前付きキャプチャグループのいずれかです。

    特定のグループが特定の入力に一致するかどうかは、その定義には関係ありません。たとえば、パターン(Yes)|(No)には2つのグループ((Yes)グループ1、(No)グループ2)がありますが、特定の入力に一致できるのはそのうちの1つだけです。

  4. Matcher.find()正規表現がいくつかの部分文字列で一致した場合、への呼び出しはtrueを返します。開始点を確認することで、一致したグループを判別できます。-1の場合、グループは一致しませんでした。その場合、終了も-1になります。find()またはへの呼び出し後に実際に一致したキャプチャグループの数を示す組み込みのメソッドはありませんmatch()。各グループの開始を見て、これらを自分で数える必要があります。

  5. 後方参照に関しては、正規表現チュートリアルの内容にも注意してください。

    何も一致しなかったキャプチャグループへの逆参照と、一致にまったく参加しなかったキャプチャグループへの逆参照には違いがあります。

于 2010-06-04T20:09:54.783 に答える
5

要約すると、

1)演算子の優先順位規則により、2つのパターンは異なる結果をもたらします。

  • (?:Yes|No)(.*)End一致(はいまたはいいえ)の後に。*終了
  • (?:Yes)|(?:No)(.*)End一致する(はい)または(いいえの後に。*終了)

Matcher2)2番目のパターンでは、グループ数は1ですが、メソッド呼び出しによって返される結果の(必ずしも直感的ではない)意味のため、-1の開始と終了になります。

  • Matcher.find()一致するものが見つかった場合はtrueを返します。あなたの場合、試合は(?:Yes)パターンの一部でした。
  • Matcher.groupCount()キャプチャグループが実際に試合に参加したかどうかに関係なく、パターン内のキャプチャグループの数を返します。あなたの場合(?:Yes)、パターンの非キャプチャ部分のみが試合に参加しましたが、キャプチャ(.*)グループはまだパターンの一部であったため、グループ数は1です。
  • Matcher.start(n)n番目のキャプチャグループMatcher.end(n)と一致するサブシーケンスの開始インデックスと終了インデックスを返します。あなたの場合、全体的な一致が見つかりましたが、キャプチャグループは一致に参加しなかったため、サブシーケンスをキャプチャしなかったため、-1の結果になります。(.*)

3)(コメントで尋ねられた質問。)サブシーケンスを実際にキャプチャしたキャプチャグループの数を決定するためにMatcher.start(n)、0からMatcher.groupCount()非-1の結果の数を数えるまで繰り返します。(これMatcher.start(0)は、パターン全体を表すキャプチャグループであり、目的のために除外することをお勧めします。)

于 2010-06-07T11:36:06.210 に答える
3

「|」の優先順位のため パターン内の演算子の場合、2番目のパターンは次と同等です。

(?:Yes)|((?:No)(.*)End)

あなたが欲しいのは

(?:(?:Yes)|(?:No))(.*)End
于 2010-06-04T20:13:42.170 に答える
1

AND正規表現を使用する場合は、暗黙の演算子が機能していることを覚えておくことが重要です。java.util.regex.Patternこれは、論理演算子をカバーするためのJavaDocから見ることができます。

論理演算子
XYXの 後にYX
| Y XまたはY
(X)Xのいずれか(キャプチャグループとして)

これは、2番目のパターンのでAND優先されます。OR2番目のパターンは。と同等
(?:Yes)|(?:(?:No)(.*)End)です。
最初のパターンと同等にするためには、次のように変更する必要があります。
(?:(?:Yes)|(?:No))(.*)End

于 2010-06-04T20:27:06.723 に答える