はじめに (対象読者・この記事でわかること)
本記事は、Javaで文字列解析を行う際に正規表現を活用したいエンジニア・プログラマを対象としています。特に、価格表記や通貨シンボルを抽出したいシーンで「¥¥d.+?yen」というパターンが登場しますが、その構造や動作が曖昧な方が多いはずです。この記事を読み進めることで、以下が実現できるようになります。
- 「¥¥d.+?yen」の各構成要素が何を意味しているかを正確に理解できる
- Java の
PatternとMatcherを用いて実際に文字列から目的の部分を抽出するコードが書ける - 正規表現実装時に起こりやすい落とし穴とその回避策を把握できる
正規表現は一見すると暗号のように見えますが、正しく理解すれば強力なテキスト処理ツールになります。ぜひ実務に活かしてください。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。
- Java の基本的な文法(変数宣言、メソッド定義など)
java.util.regexパッケージのPatternとMatcherの基本的な使い方(概念だけでも可)
正規表現「¥¥d.+?yen」の概要・背景
¥¥d.+?yen は、円記号(¥)で始まり、その後に1桁以上の数字が続き、さらに任意の文字列が最短マッチで続き、最後に「yen」という文字列で終わるというパターンを表現します。構成要素を順に見ていきましょう。
| 要素 | 意味 | 解説 |
|---|---|---|
¥¥ |
エスケープされた円記号 | 正規表現では ¥ がエスケープ文字になるため、文字通りの円記号を表すには ¥¥ と二重に書く必要があります。Java の文字列リテラル内でも \\ でエスケープするため、最終的に "\\\\d.+?yen" と記述します。 |
d |
任意の数字(0-9) | \d は「digit」の略で、数字1文字を意味します。 |
.+? |
任意の文字が1回以上 最短 でマッチ | . は任意の1文字、+ は「1回以上の繰り返し」、? は「貪欲でなく最短マッチ」を指示します。これにより「¥123abc yen」から「abc 」だけが抽出されます。 |
yen |
リテラル文字列「yen」 | 正規表現の最後に固定文字列「yen」が続くことを示します。 |
この正規表現は、たとえば「¥5000yen」や「¥12,345円 yen」など、円記号で始まり「yen」で終わる価格表記を抽出したいケースに有用です。特に、Web API のレスポンスやログファイルから通貨情報を抜き出す際に活躍します。
正規表現の実装と応用例
以下では、実際に Java コードで ¥¥d.+?yen を用いる手順をステップごとに解説します。サンプルコードは JDK 8 以降で動作します。
ステップ1:Pattern オブジェクトの作成
Javaimport java.util.regex.Pattern; import java.util.regex.Matcher; public class YenRegexDemo { // 正規表現文字列は Java のエスケープが必要 private static final String REGEX = "\\\\d.+?yen"; private static final Pattern PATTERN = Pattern.compile(REGEX); }
ポイント:
- Java の文字列リテラルでは
\をエスケープするため、正規表現中の\dは"\\d"と書きます。 - さらに円記号自体もエスケープが必要なため、最終的に
"\\\\d.+?yen"となります。
ステップ2:Matcher で対象文字列を検索
Javapublic static void main(String[] args) { String text = "商品A: ¥12345yen, 商品B: ¥9,999yen, 無料: yen"; Matcher matcher = PATTERN.matcher(text); while (matcher.find()) { System.out.println("マッチした文字列: " + matcher.group()); } }
実行結果:
マッチした文字列: ¥12345yen
マッチした文字列: ¥9,999yen
matcher.find()は次のマッチを順に探します。matcher.group()でマッチ全体(¥からyenまで)を取得できます。
ステップ3:最短マッチの効果を確認
.+? が「最短」マッチであることを確認するため、文字列に複数の yen が含まれるケースを試します。
JavaString complex = "¥1000abc yen XYZ ¥2000defgh yen"; Matcher m = PATTERN.matcher(complex); while (m.find()) { System.out.println(m.group()); }
結果:
¥1000abc yen
¥2000defgh yen
.+? が最短でマッチするため、¥1000abc yen の abc 部分だけが対象となり、後続の XYZ には跨がりません。貪欲マッチ (.+) にすると ¥1000abc yen XYZ ¥2000defgh yen 全体が1回のマッチとなり、意図しない結果になります。
ハマった点やエラー解決
| 症状 | 原因 | 解決策 |
|---|---|---|
コンパイルエラー PatternSyntaxException |
正規表現中の \ が適切にエスケープされていない |
Java の文字列リテラルでは \\ と二重に書く。円記号は \\\\ と記述。 |
| マッチが全く取得できない | 入力文字列に実際の円記号が全角(¥)ではなく半角(¥)や Unicode の別表記(U+00A5) | 正規表現を [\u00A5\\uFFE5] のように複数の円記号を許容する形に変更。 |
.+? が期待通りに最短マッチしない |
DOTALL フラグが有効で改行もマッチ対象になる |
必要に応じて Pattern.compile(REGEX, Pattern.DOTALL) の有無を見直す。 |
解決策まとめ
- エスケープの二重化: Java の文字列では
\を\\、円記号は\\\\にする。 - 全角円記号対応: 必要なら文字クラスに複数の円記号コードポイントを入れる。
- フラグの確認:
Pattern.MULTILINEやPattern.DOTALLがマッチ結果に影響するので、意図しないフラグは外す。
これらを踏まえて実装すれば、安定した文字列抽出が可能になります。
まとめ
本記事では、Java における正規表現 ¥¥d.+?yen の構造と実装方法を詳細に解説しました。
- 構成要素の意味:
¥¥は円記号、\dは数字、.+?は最短マッチの任意文字列、yenはリテラル文字列です。 - 実装手順: Pattern の作成 → Matcher で検索 → 最短マッチの確認という流れでコードを書きました。
- ハマりポイント: エスケープ不足や文字種の違い、正規表現フラグの影響が主な課題でしたが、適切な対策で解決できます。
この記事を通じて、読者は「円記号で始まり yen で終わる文字列」を正確に抽出できるようになり、ログ解析やデータクレンジングの品質が向上するでしょう。次回は、複数通貨記号やロケール別フォーマットへの拡張方法を取り上げる予定です。
参考資料
- Java Platform SE 8 Documentation – java.util.regex.Pattern
- 正規表現入門 – Wikipedia
- 「Effective Java」第3版, Joshua Bloch, Addison-Wesley, 2018
