【Java学習|豆知識】Java正規表現の極意:置換文字列で「$n」を使ってマッチしたグループを再利用する

1. 導入:なぜこのテクニックが重要なのか

Javaの正規表現で文字列を置換する際、単に「特定の文字列を別の文字列に置き換える」だけでは不十分なケースが多々あります。「マッチした内容の一部を保持したまま、順番を入れ替える」あるいは「特定のパターンを抽出して装飾を加える」といった動的な処理を行いたい場合、置換文字列内での番号参照($n)が非常に強力な武器となります。これを知っているだけで、冗長なコードを書かずに洗練された文字列操作が可能になります。

2. 基礎知識:正規表現のグループ化と参照

Javaの正規表現では、丸括弧 `()` を使うことで「グループ」を作成できます。正規表現エンジンは、左から現れる順にグループ番号(1, 2, 3…)を割り当てます。
置換メソッドである `Matcher.replaceAll()` や `Matcher.replaceFirst()` を使用する際、置換先の文字列に `$1`, `$2` と記述すると、正規表現でマッチした各グループの内容を、そのまま置換後の文字列に埋め込むことができます。

3. 実装・解決策

手順は非常にシンプルです。
1. 対象のパターンを `()` で囲み、グループ化する。
2. 置換文字列の中で、`$1`, `$2` のように、取得したいグループ番号を指定する。
この際、`$` 記号そのものを文字列として出力したい場合は `\$` とエスケープする必要がある点に注意してください。

4. サンプルプログラム

以下は、日付フォーマット「yyyy-MM-dd」を「dd/MM/yyyy」に変換する実用的なコード例です。

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

public class RegexReplaceSample {
    public static void main(String[] args) {
        // 対象の文字列(日付)
        String input = "2023-10-25";
        
        // パターン定義:ハイフンで区切られた3つのグループを作成
        // 第1グループ: 年, 第2グループ: 月, 第3グループ: 日
        String regex = "(\\d{4})-(\\d{2})-(\\d{2})";
        
        // 置換文字列:$3(日) / $2(月) / $1(年) の順に並び替える
        String replacement = "$3/$2/$1";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        // 置換処理の実行
        String result = matcher.replaceAll(replacement);
        
        // 結果出力
        System.out.println("変換前: " + input);
        System.out.println("変換後: " + result);
    }
}

5. 応用・注意点

現場で活用する上で、以下の点に注意してください。

グループ番号のカウントミスに注意
グループは「左括弧 `(` が登場した順」に番号が振られます。入れ子構造になっている場合、番号が直感とずれることがあるため、複雑な正規表現を扱う際は注意が必要です。

名前付きグループの活用
Java 7以降では、`(?<name>…)` という形式で名前付きグループを定義できます。しかし、置換文字列内での参照は依然として `$n`(番号)が基本です。可読性を上げるために、大規模な置換ロジックではコメントを丁寧に記述することを推奨します。

特殊文字の扱い
もし置換結果に `$` 記号自体を含めたい場合は、`Matcher.quoteReplacement(“$”)` を使うか、`\$` とエスケープすることを忘れないでください。これを忘れると、Javaが「番号参照」だと勘違いして `IllegalArgumentException` をスローすることがあります。

コメント

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