Java regexキャプチャグループインデックス


113

私は次の行を持っています、

typeName="ABC:xxxxx;";

私は言葉をフェッチする必要がありABC

私は次のコードスニペットを書きました、

Pattern pattern4=Pattern.compile("(.*):");
matcher=pattern4.matcher(typeName);

String nameStr="";
if(matcher.find())
{
    nameStr=matcher.group(1);

}

だから私は置けばgroup(0)私が手ABC:が、私は置けばgroup(1)それがABC私が知りたいので、

  1. この何をない0とは1どういう意味ですか?誰かが良い例を使って私を説明できればもっと良いでしょう。

  2. 正規表現パターンにa :が含まれているのに、なぜgroup(1)結果がそれを省略するのですか?グループ1は括弧内のすべての単語を検出しますか?

  3. したがって、次のようにさらに2つの括弧を付けると、\\s*(\d*)(.*)2つのグループになりますか?パーツgroup(1)を返却して(\d*)パーツをgroup(2)返却し(.*)ますか?

コードスニペットは、混乱を解消する目的で提供されています。それは私が扱っているコードではありません。上記のコードString.split()は、はるかに簡単な方法で実行できます。

回答:


182

キャプチャとグループ化

キャプチャグループを (pattern)作成グループ取り込む性質を。

よく見られる(そして使用される)関連するものはです(?:pattern)。これは、プロパティをキャプチャせずにグループを作成するため、非キャプチャグループと呼ばれます。

グループは通常、パターンのシーケンスを繰り返す必要がある場合に使用されます。たとえば(\.\w+)+^(0*1|1*0)$^、次に、0*1または1*0次に$)と^0*1|1*0$^0*1または1*0$)のように、交替が有効になる場所を指定するために使用されます。

キャプチャグループは、グループ化とは別に、キャプチャグループ内のパターンに一致するテキストも記録します(pattern)。の例を使用すると、は(.*):.*ととABC:一致し:.*はキャプチャグループ内にあるため、(.*)テキストABCはキャプチャグループ1に記録されます。

グループ番号

パターン全体は、グループ番号0 として定義されています。

パターン内のキャプチャグループは、1からインデックスを開始します。インデックスは、キャプチャグループの左括弧の順序によって定義されます。例として、以下のパターンの5つのキャプチャグループすべてを次に示します。

(group)(?:non-capturing-group)(g(?:ro|u)p( (nested)inside)(another)group)(?=assertion)
|     |                       |          | |      |      ||       |     |
1-----1                       |          | 4------4      |5-------5     |
                              |          3---------------3              |
                              2-----------------------------------------2

グループ番号は\n、パターンおよび$n置換文字列の後方参照で使用されます。

他の正規表現フレーバー(PCRE、Perl)では、サブルーチン呼び出しで使用することもできます

特定のグループに一致するテキストにでアクセスできますMatcher.group(int group)。グループ番号は、上記のルールで識別できます。

一部の正規表現フレーバー(PCRE、Perl)には、 ブランチリセット機能があります。これにより、同じ番号を使用し、交互の異なるブランチのグループキャプチャできます。

グループ名

Java 7から、 名前付きキャプチャグループをと (?<name>pattern)一致するコンテンツにアクセスできますMatcher.group(String name)。正規表現は長くなりますが、コードは、正規表現と一致または抽出しようとしているものを示しているため、より意味があります。

グループ名は\k<name>、パターンおよび${name}置換文字列の後方参照で使用されます。

名前付きのキャプチャグループには、同じ番号付け方式で番号が付けられているため、からもアクセスできますMatcher.group(int group)

内部的には、Javaの実装は名前からグループ番号にマップするだけです。したがって、2つの異なるキャプチャグループに同じ名前を使用することはできません。


1
うわー!非キャプチャグループについて、ネストグループの順序がどのように機能するかを説明していただき、ありがとうございます。最後にあなたの説明を読むまで、私はグループ番号がどのように機能するのか悩みました。どうもありがとう!
MMeah 2015

92

私たちの残りのために

これがどのように機能するかを示す簡単で明確な例です

正規表現: ([a-zA-Z0-9]+)([\s]+)([a-zA-Z ]+)([\s]+)([0-9]+)

ストリング: "!* UserName10 John Smith 01123 *!"

group(0): UserName10 John Smith 01123
group(1): UserName10
group(2):  
group(3): John Smith
group(4):  
group(5): 01123

ご覧のとおり、括弧で囲まれた5つのグループを作成しました。

!*と*!それをより明確にするためにどちらかの側に。これらの文字はいずれもRegExにはないため、結果では生成されないことに注意してください。Group(0)は、一致した文字列全体(1つの行にあるすべての検索条件)を提供するだけです。スペース文字が検索条件に含まれていないため、グループ1は最初のスペースの直前で停止します。グループ2と4は単に空白であり、この場合は文字通りスペース文字ですが、タブや改行などの場合もあります。グループ3はスペースを含めています。これは、検索条件に含めたためです。

これが理にかなっているといいのですが。


1
初心者にとって理解しやすい完璧な例です。これはpythonでの正規表現のグループ化と同じですか?それとも何か違いがありますか?私は正規表現の初心者です。そのため、両方の言語で少し混乱しています。
Mani

1
これは有効なJava正規表現ではありません:バックスラッシュは2重にする必要があります。
Nicolas Raoul 2017年

1
@NicolasRaoul:二重のバックスラッシュは文字列リテラルのエスケープ構文が原因です。実際の正規表現の構文(つまり、正規表現を含む文字列をコンソールに出力する場合)では、二重の円記号は必要ありません。
nhahtdh 2017年

@NicolasRaoul有能なIDEを使用して私の正規表現文字列を実際のJavaコードにコピーして貼り付ける場合、IDEは必要に応じてエスケープスラッシュを適切にフォーマットします。しかし、私の正規表現は、技術的、構文的に正しいか、それは...少し明るく...☺正規表現コードと(非常に具体例を用いて)得られた結果との間の関連性を実証することである主な目的を果たす
マイケル・シムズ

44

括弧()は、正規表現フレーズのグループ化を有効にするために使用されます。

group(1)は括弧の間にある文字列が含まれている(.*)ので.*、この場合は

そして group(0)、一致した文字列全体が含まれます。

さらに多くのグループ(read (...))がある場合は、次のインデックス(2、3など)を持つグループに入れられます。


2
だから、私は括弧を追加することが実際にグループを作成するためのものであることを正しいですか
P basak 2013年

3
はい、そう言えます。
ミハルボレック2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.