正規表現

Javaで正規表現を扱うには java.util.regexパッケージを利用します。Javaでの正規表現の用途は 大別すると次の通りになります。

  • ある文字列が正規表現パターンと一致するか、または正規表現パターンが含まれるかどうかの判定(一致判定)。また一致する文字列の抽出
  • 正規表現パターンに一致する文字列を置換
  • ある文字列を正規表現パターンで分割

Javaで正規表現を使うには 大きく分けて2通りの方法があります。

  • 事前に正規表現パターンをコンパイルしておく方法
  • 正規表現パターンをコンパイルせずに、検索・置換・分割を行う際に 正規表現パターンを指定する方法(ユーティリティ)

正規表現パターンによる一致判定等を行う前に、正規表現パターンのチェックをして 正規表現エンジンが解析できるようにするためのデータ構造を構築する処理を行います。同じ正規表現パターンで 繰り返し一致判定等を行う場合は この事前の処理が冗長となるため、事前処理をコンパイルという形で 独立して呼び出せるようになっています。

そのため 同じ正規表現パターンで何度も一致判定等を行う場合は、事前にコンパイルをした方が冗長な処理を省けます。一方で 同じ正規表現パターンを1度しか使わない場合は 事前にコンパイルしないユーティリティを使う方が便利です

ただし、ユーティリティを使う場合は「大文字・小文字の区別をしない」とか「複数行モードを有効にする」といった 細かい制御を行うことができません。また 一致判定では 部分一致の判定ができず、抽出を行うこともできません。そのため 正規表現のフル機能を利用したい場合は、必然的に事前にコンパイルする方法を選択することになります

 

事前にコンパイルをする使い方

主にPatternクラスとMatcherクラスを使います。Patternクラスで正規表現をコンパイルしMatherクラスがマッチ操作を行い 適用結果を保持します。基本的な流れは次のようになります。

  1. 正規表現のパターンをコンパイルして Patternオブジェクトを作成します。
  2. Patternオブジェクトの正規表現に 適用したい文字列を渡して Matherオブジェクトを作成します。
  3. Matcherオブジェクトにて 一致判定・抽出・置換などを行います。

分割を行う場合は 1ステップ減って次のようになります。

  1. 正規表現のパターンをコンパイルして Patternオブジェクトを作成します。
  2. Patternオブジェクトに 分割したい文字列を渡して 分割を行います。

一致判定

Matherにて一致判定を行う場合、全体一致か部分一致かでメソッドが異なります。

  • 正規表現パターンが 全体と一致するかどうか判定する場合には matches()メソッドを使います。
  • パターンが 先頭から一致するかどうか判定する場合には lookingAt()メソッドを使います。
  • パターンが どこかの部分と一致するかどうか判定する場合には find()メソッドを使います。
    find()の場合は 複数箇所で一致する可能性がありますので、while文などのループと組み合わせて使うことができます。

matches()による一致判定の例です。一部分が一致していても、全体が一致していないと true にはなりません。

 

 

続いて lookingAt()による一致判定の例です。先頭が一致していないと trueにはなりません。

 

 

最後に find()による一致判定の例です。二度目のfind()の呼び出しでは 一度目で一致した部分の次から判定を開始します。一致するパターンが見つかる間はtrueを返します。一致するパターンがなくなるとfalseが返ります。

 

 

抽出

一致箇所を抽出したい場合は、正規表現パターンを丸括弧 () で囲みます。Matcherのgroup()メソッドにより 一致箇所を抽出することができます。group()メソッドの引数で 正規表現パターンの丸括弧の位置(左からの出現順)を指定します。ここで注意する点は、位置の開始は1オリジンであることです。引数なしのgroup()と group(0) は一致したパターン全体を返します。

丸括弧がネストされている場合は、左から数えて “(” が出現した順番が位置となります。例えば “((AB)((CD)(EF)))” というパターンの場合は 次のようになります。

実行結果は次のようになります。

位置指定では 分かりづらく 間違いも発生し易いため、名前を付けて指定することもできます正規表現パターンの中で “?<名前>” の形で名前付けをします。group()メソッドでは 正規表現パターンの中で付けた名前を指定します。存在しない名前を指定すると IllegalArgumentExceptionが発生します。

 

lookingAt()やfind()を使った場合も 同様に group()メソッドで一致箇所を抽出することができます。find()を使った例を次に挙げます。

実行結果は次のようになります。

 

 

置換

正規表現パターンで一致した箇所を置換するには MatcherクラスのreplaceFirst()、replaceAll()メソッドを使います。

 

 

分割

正規表現パターンで指定した区切り文字で分割するには Patternオブジェクトのsplit()メソッドを使います。分割するにはMatcherを使わず Patternを使うことがポイントです。

また、配列ではなく Stringのストリームとして返すsplitAsStream()メソッドも用意されています。

 

 

事前にコンパイルをしない使い方(ユーティリティ)

同じ正規表現パターンによる一致判定・置換・分割を1度しか行わない場合は、事前にコンパイルをしなくても呼び出せる ユーティリティメソッドを使うのが便利です。それぞれ 次のようなユーティリティが用意されています。

  • 一致判定:Stringクラスのmatches()メソッド、Patternクラスのmatches()クラスメソッド
  • 置換:StringクラスのreplaceAll()、replaceFirst()メソッド
  • 分割:Stringクラスのsplit()メソッド

ただし、一致判定用のユーティリティのmatches()は 全体一致の判定を行うため部分一致には使えません。また 呼び出し側に 一致結果を抽出するためのMatcherオブジェクトが返らないため、抽出を行うことができません。更に、「大文字・小文字の区別をしない」とか「複数行モードを有効にする」といった細かい制御を指定することができません(これらのオプションは 事前にコンパイルをする際に Pattern.compile()の引数で指定するためです)。

 

 

 

 

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