Java | Java 標準ライブラリ:Matcher の使い方

Java Java
スポンサーリンク

Matcher は「正規表現パターンを文字列に当てていく実行役」

前回の Pattern の話とつなげると、役割分担はこうです。

Pattern
「正規表現(パターン)そのもの」を表す。何度も使い回せる“型”のような存在。

Matcher
「このパターンを、この文字列に当ててみよう」という“実行役”。
マッチング結果(どこに一致があったか、どんなグループが取れたか)も覚えてくれる。

流れとしては、

  1. 正規表現から Pattern を作る(コンパイルする)
  2. Pattern から Matcher を作る(どの文字列に当てるか決める)
  3. Matcher のメソッド(matches, find, group など)で結果を調べたり、置換したりする

という順番になります。

ここからは、この Matcher を「どう使うか」「どこでハマりやすいか」を、例をまじえて整理していきます。


基本の流れ:Pattern → Matcher → matches / find

全体がパターンに一致しているかを調べる(matches)

まずは一番シンプルな使い方から。

数字だけの文字列かどうかをチェックする例です。

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

public class MatcherExample {

    public static void main(String[] args) {
        Pattern pattern = Pattern.compile("\\d+");   // 1文字以上の数字
        Matcher matcher = pattern.matcher("12345");

        boolean result = matcher.matches();
        System.out.println(result);  // true
    }
}
Java

ここでのポイントは matches()

文字列全体がパターンにマッチしているか

をチェックしている、という点です。

"12345" は「数字だけ」なので true。
"abc123" なら false になります。

Matcher m = pattern.matcher("abc123");
System.out.println(m.matches());  // false
Java

「入力値の形式チェック」のように、「全部がその形であってほしい」ときは matches() を使うのが基本です。

部分一致を探す(find)

今度は「文字列の中にパターンに合う部分があるか」を調べたい場合です。
例えば、文字列の中に含まれている数字を全部抜き出したいとします。

Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("abc123def45xyz6");
Java

ここで matches() を使うと false です。
全体が数字だけではないからですね。

部分一致を見つけたいときは find() を使います。

while (matcher.find()) {
    System.out.println("見つかった: " + matcher.group());
}
Java

出力はこんな感じになります。

見つかった: 123
見つかった: 45
見つかった: 6

find() は「次の一致箇所があるか?」を順番に探していくメソッドです。
while (matcher.find()) の形で使うと、「全部のマッチ」を順番に列挙できます。


group / start / end で「どこがマッチしたか」を取り出す

group() で一致した文字列を取り出す

さっきの例で使った group() は、「今のマッチで一致した文字列そのもの」を返します。

Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("abc123xyz");

if (matcher.find()) {
    System.out.println(matcher.group());  // 123
}
Java

matches() を使った場合でも、true のあとに group() を呼べば、
「全体一致の文字列」が返ってきます。

Matcher matcher = pattern.matcher("12345");
if (matcher.matches()) {
    System.out.println(matcher.group());  // 12345
}
Java

start と end で位置情報を知る

「どこに一致したか」まで知りたいときは start()end() が使えます。

Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher("abc123def");

if (matcher.find()) {
    System.out.println("一致: " + matcher.group());        // "123"
    System.out.println("開始位置: " + matcher.start());    // 3
    System.out.println("終了位置: " + matcher.end());      // 6
}
Java

start() は「文字列のどのインデックスから始まったか」(0 始まり)。
end() は「どこまでか(終端の1つ後のインデックス)」です。

この位置情報を使うと、自分で文字列を分割したり、
前後の文脈を参照したり、といった処理が書けるようになります。


グルーピング(())と group(n) の使い方(ここ大事)

括弧で「拾いたい部分」を囲う

正規表現の () は「グループ」を作ります。
Matcher では、グループごとに個別に取り出せます。

例えば「年-月-日」の形式から、それぞれの数字を取り出したい場合を考えましょう。

String text = "2025-12-31";
Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher matcher = pattern.matcher(text);

if (matcher.matches()) {
    String year  = matcher.group(1);  // 最初の ( ... )
    String month = matcher.group(2);  // 2番目の ( ... )
    String day   = matcher.group(3);  // 3番目の ( ... )

    System.out.println(year);   // 2025
    System.out.println(month);  // 12
    System.out.println(day);    // 31
}
Java

ここでのポイントは、

group(0) は「全体にマッチした文字列」(”2025-12-31″)
group(1) が1番目の括弧、group(2) が2番目の括弧…

という対応になっていることです。

この仕組みを使うと、「正規表現で形をチェックしながら、中の必要な部分だけ取り出す」ということができます。

find と組み合わせて複数マッチから情報を抜き出す

例えば、文章の中に日付がいくつも出てくるケース。

String text = "イベントは2025-12-31に開催され、予備日は2026-01-10です。";
Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher matcher = pattern.matcher(text);

while (matcher.find()) {
    String year  = matcher.group(1);
    String month = matcher.group(2);
    String day   = matcher.group(3);
    System.out.println("見つかった日付: " + year + "/" + month + "/" + day);
}
Java

出力は、

見つかった日付: 2025/12/31
見つかった日付: 2026/01/10

のようになります。

find() で「次のマッチ」を探し、
それぞれのマッチで group(n) を使って必要な部分を取り出す。
この組み合わせが、Matcher の強みの一つです。


置換に使う:replaceAll / replaceFirst

単純な置換:全部置き換える

Matcher は、「マッチした部分を置き換える」こともできます。

例えば、「数字だけを # に置き換える」例です。

String text = "商品Aは100円、商品Bは250円です。";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);

String replaced = matcher.replaceAll("#");
System.out.println(replaced);
// 商品Aは#円、商品Bは#円です。
Java

replaceAll は、「マッチしたすべての部分」を置き換えます。
replaceFirst を使うと、最初の1箇所だけ置き換えます。

String replacedFirst = matcher.replaceFirst("#");
System.out.println(replacedFirst);
// 商品Aは#円、商品Bは250円です。
Java

元の文字列の他の部分は自動でコピーされる

replaceAll / replaceFirst を使うと、

マッチした部分 → 指定した文字列に変換
それ以外の部分 → そのままコピー

という処理をいい感じにやってくれます。

「マッチしない部分も含めて、全文を組み立て直す」のを自分でやると結構大変なので、
まずはこれらのメソッドで済むケースから使い始めると良いです。


reset / region など、Matcher の動きを制御する

reset で同じ Matcher を再利用する

Matcher は、一度 find() を進めたりすると内部に「今どこまで見たか」の状態を持ちます。
同じ文字列に対して、最初から検索し直したいときは reset() を使います。

Matcher matcher = pattern.matcher("abc123xyz");
while (matcher.find()) {
    System.out.println(matcher.group());
}

matcher.reset();  // 最初の状態に戻す

while (matcher.find()) {
    System.out.println("再検索: " + matcher.group());
}
Java

reset("新しい文字列") のように、
「同じ Pattern だが、別の文字列に対して再利用する」こともできます。

matcher.reset("foo456bar");
while (matcher.find()) {
    System.out.println(matcher.group());  // 456
}
Java

頻繁にパターンを使い回す場面では、「Pattern は1つだけ作る → Matcher を reset しながら使う」というスタイルも可能です。

region で検索範囲を絞る(少し上級)

文字列の一部だけを対象に検索したいときは region(int start, int end) も使えます。

String text = "abc123def456ghi";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);

// インデックス 3〜10 だけを検索対象にする
matcher.region(3, 10);

while (matcher.find()) {
    System.out.println("region内で見つかった: " + matcher.group());
}
Java

この例だと、"123def456" の範囲だけで数字を探します。
全体に対して find したくないケース(部分だけ検査したい)で使われますが、
初心者のうちは「そんな機能もあるんだ」くらいの理解で十分です。


まとめ:Matcher を使うときに覚えておきたいパターン

初心者向けに、Matcher の使い方をざっくりまとめるとこうなります。

Pattern.compile(正規表現) でパターンを作る
pattern.matcher(文字列) で Matcher を作る
「全体一致をチェックしたい」→ matcher.matches()
「文字列の中から全部見つけたい」→ while (matcher.find()) { matcher.group() }
「グループごとに取り出したい」→ 正規表現で (…) を使って、matcher.group(1), group(2)…
「位置も知りたい」→ matcher.start(), matcher.end()
「置換したい」→ matcher.replaceAll(), matcher.replaceFirst()

ここまで押さえておけば、Matcher でできることのかなりの部分は使いこなせます。

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