【Java学習|豆知識】Java正規表現の極意:Matcher.replaceAllで文字列操作を自在に操る

導入:なぜMatcher.replaceAllが重要なのか

Javaで文字列を操作する際、単なるString.replaceでは対応できない複雑なパターン置換に直面することは多々あります。例えば、「特定の形式の電話番号をマスクしたい」「ログ内の特定フォーマットを抽出して加工したい」といったケースです。java.util.regexパッケージのMatcher.replaceAllメソッドを活用すれば、柔軟かつ堅牢な置換処理が実装可能です。

基礎知識:正規表現とMatcherの仕組み

Javaの正規表現は、主にPatternクラスとMatcherクラスで構成されます。
Pattern: 正規表現パターンをコンパイルしたオブジェクトです。
Matcher: パターンを文字列に適用し、検索・置換を行うエンジンです。
Named groups(名前付きキャプチャグループ)を使用すると、正規表現内でグループに名前を付けられ、置換時にその名前を参照できるため、コードの可読性が飛躍的に向上します。

実装:置換のステップ

1. Pattern.compileで正規表現をコンパイルします。
2. matcherメソッドで対象文字列を渡してMatcherインスタンスを作成します。
3. replaceAllメソッドに置換後の文字列を指定します。この際、グループ参照($1や${name})を使用することで、マッチした内容を再利用できます。

サンプルプログラム

以下のコードは、ログデータ内の「日付形式」を変換し、名前付きグループを使って特定箇所を置換する例です。

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

public class RegexExample {
    public static void main(String[] args) {
        // yyyy-mm-dd形式をdd/mm/yyyy形式に変換する正規表現
        // 名前付きグループを使用して年、月、日をキャプチャ
        String regex = "(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})";
        String input = "本日の日付は 2023-10-27 です。昨日は 2023-10-26 でした。";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);

        // ${name} を使って名前付きグループを参照して置換
        String result = matcher.replaceAll("${day}/${month}/${year}");

        // 結果を出力: 27/10/2023 と 26/10/2023 に変換される
        System.out.println("変換前: " + input);
        System.out.println("変換後: " + result);
    }
}

応用・注意点:現場でのベストプラクティス

1. パフォーマンスへの配慮
Patternオブジェクトの生成はコストがかかります。ループ内で何度も同じパターンを使用する場合は、必ずstatic finalフィールドとして定義し、再利用してください。

2. エスケープの罠
Javaの文字列リテラル内ではバックスラッシュ(\)を重ねる必要があります。正規表現で「数字」を表す \d は、Javaコード上では “\\d” と記述しなければならない点に注意してください。

3. 意図しないマッチングの回避
replaceAllは正規表現の特性上、貪欲(Greedy)なマッチングを行います。置換範囲が広すぎて困る場合は、「?」を付与して非貪欲(Lazy)なマッチングに変更するなどの工夫が必要です。

正規表現を正しく使いこなせば、文字列処理のコード量は劇的に減り、メンテナンス性も向上します。ぜひ日々の開発に取り入れてみてください。

コメント

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