グループ化のみ行う括弧(?:..)

広告

パターン内を括弧()を使ってグループ化することで、グループ毎にマッチした文字列を取得することができました。ただ、括弧はこのような目的以外にも使用しています。例えば量指定子の対象をグループ化したり、選択の候補をグループ化したりするのに使用してきました。

"(¥d)+"
"200(7|8|9)"

このような場合でも括弧で囲われていると、指定したインデックスのグループにマッチした文字列を取得することができます。ただし、グループは前のページで記載した通り、括弧が記述された順にインデックスが割り当てられていきます。単に選択をグループ化するために括弧を使った場合でもインデックスが割り当てられてしまいます。その為、グループのインデックス数でループを回している場合などは取得する必要の無いグループの値も取得してしまうことになります。

またグループにマッチした部分文字列は参照できるように別途保存されています。実際には使わない値を保存しておくことは資源の無駄となります。

そこでパターンの中でグループ化のために括弧を使ってはいるが、インデックス割り当ては行わずマッチする部分文字列の参照もしないという場合には()の代わりに(?:)を使います。例えば次のように記述します。

"(?:¥d)+"
"200(?:7|8|9)"

(?:)を使用することで括弧としての意味はそのままですが、インデックスを指定してマッチした部分文字列を取得するなどは行えなくなります。

次の2つのパターンを見てください。

"(200(7|8|9))year"
"(200(?:7|8|9))year"

パターン"(200(7|8|9))year"では2つのインデックスを指定してマッチする文字列を参照できますが、パターン"(200(?:7|8|9))year"ではマッチした部分文字列を参照できるグループは1つだけです。

例えば次のように記述します。

String str = "2009year";
String regex = "(200(?:7|8|9))year";
Pattern p = Pattern.compile(regex);

Matcher m = p.matcher(str);
if (m.find()){
  String matchstr = m.group();
  System.out.println(matchstr + "の部分にマッチしました");

  for (int i = 0 ; i <= m.groupCount() ; i++){
    System.out.println("group" + i + ":" + m.group(i));
  }
}

サンプルプログラム

では実際に試してみます。

JSample3_1.java

import java.util.regex.Pattern;
import java.util.regex.Matcher;

class JSample3_1{
  public static void main(String args[]){
    String str1 = "2009year";

    String regex1 = "(200(7|8|9))year";
    Pattern p1 = Pattern.compile(regex1);

    String regex2 = "(200(?:7|8|9))year";
    Pattern p2 = Pattern.compile(regex2);

    System.out.println("パターン : " + regex1);

    check(p1, str1);

    System.out.println("パターン : " + regex2);

    check(p2, str1);
  }

  private static void check(Pattern p, String target){
    Matcher m = p.matcher(target);

    if (m.find()){
      int start = m.start();
      int end = m.end();
      System.out.println("○ " + target);
      System.out.println("[全体] " + m.group());
      for (int i = 1 ; i <= m.groupCount(); i ++){
        System.out.println("[Group" + i + "] " + m.group(i));
      }
    }else{
      System.out.println("× " + target);
    }
  }
}

ではコンパイルを行った上で実行してみます。

p3-1

( Written by Tatsuo Ikura )