【Java学習|初心者向け】Java正規表現を使いこなす!Matcher.start()とend()で位置情報を取得する方法

1. 導入: なぜ位置情報が必要なのか?

Javaで文字列を検索・加工する際、正規表現は非常に強力です。しかし、「何にマッチしたか」だけでなく、「文字列のどこ(何文字目から何文字目まで)にマッチしたか」を知りたい場面も多くあります。例えば、特定のキーワードをハイライトしたり、ログデータから特定範囲の情報を抽出したりする際に、Matcherクラスのstart()とend()メソッドが欠かせません。これらを使いこなすことで、文字列操作の幅が大きく広がります。

2. 基礎知識: 正規表現とインデックス

Javaで正規表現を扱うには、java.util.regexパッケージの「Pattern」と「Matcher」クラスを使います。
Pattern: 正規表現のルールをコンパイルしたものです。
Matcher: Patternを使って、対象文字列に対して検索やマッチングを行うエンジンです。
start(): マッチした部分の開始インデックス(0から始まる)を返します。
end(): マッチした部分の直後のインデックス(次の文字の位置)を返します。

この「end()」が返す値は、Javaのsubstringメソッドの「終了位置(その位置を含まない)」と同じ仕様であるため、そのまま切り出し処理に使えるのが特徴です。

3. 実装/解決策: マッチした範囲を特定する

手順は非常にシンプルです。
1. Pattern.compile()で正規表現を作成する。
2. matcher()でMatcherオブジェクトを取得する。
3. find()をループさせてマッチした箇所を順次見つける。
4. その都度、start()とend()で位置を取得する。

4. サンプルプログラム: 位置情報を取得して表示する

以下のコードは、文字列の中から数値の範囲を特定し、その位置と内容を表示するプログラムです。

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

public class RegexIndexExample {
    public static void main(String[] args) {
        String input = "注文ID: 12345, 数量: 99";
        // 数字の連続にマッチする正規表現
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(input);

        System.out.println("検索対象: " + input);

        // マッチする箇所を順番に探す
        while (matcher.find()) {
            // start(): マッチした文字列の開始位置
            int start = matcher.start();
            // end(): マッチした文字列の終了位置の次
            int end = matcher.end();
            
            // マッチした文字列そのものを取得
            String match = matcher.group();

            System.out.println("発見: " + match);
            System.out.println("開始インデックス: " + start);
            System.out.println("終了インデックス: " + end);
            // substringを使って抽出も可能
            System.out.println("切り出し: " + input.substring(start, end));
            System.out.println("---");
        }
    }
}

5. 応用・注意点: 現場での活用と落とし穴

Named Groupsとの併用: Java 7以降では、正規表現内に名前付きグループ((?…))を使用できます。特定のグループの位置だけを知りたい場合は、matcher.start(“name”)のように引数にグループ名を指定することで、柔軟な位置取得が可能です。
注意点: find()メソッドを呼び出す前にstart()やend()を呼ぶと、IllegalStateExceptionが発生します。必ずループや条件分岐内で、マッチが成功した後に呼び出すようにしてください。
日本語の扱い: Javaの文字列はUnicode(UTF-16)で管理されているため、インデックスは「文字数」ではなく「char単位」です。サロゲートペアを含む特殊な文字を扱う場合は、インデックスの扱いに少し注意が必要になることを覚えておきましょう。

このインデックス情報を活用すれば、特定のパターンをハイライトしたり、置換処理を自作したりと、より高度な文字列処理が可能になります。ぜひ試してみてください。

コメント

タイトルとURLをコピーしました