正規表現とは
ある文字列に対して、「XXで始まって○○で終わる」や「○○または△△またはXXを含む」、「□の後に○△が続く」などの複雑な検索や置換を行うパターンをチェックする方法です。
例えば、日本の郵便番号にマッチするかどうかを調べるコードは、以下のようになります。
「com.cmps.regex」パッケージを作成し、その中に「Regex」クラスを作成してください。
// 郵便番号
String postCode = "123-4567";
if (postCode.matches("[0-9]{3}-[0-9]{4}")) {
System.out.println("マッチします");
} else {
System.out.println("マッチしません");
}
正規表現はマッチさせる文字のパターンを表現します。
上記の例では「”^[0-9]{3}-[0-9]{4}$”」がパターン(正規表現)になります。
正規表現を利用することで、E-mail アドレスや URL、 HTML のタグなど、より複雑な文字列のパターンを抽出したり置換したりすることができます。
正規表現のパターンなんてすべて把握することはむずかしいですが、ネットで「Java 正規表現」とでも調べたらたくさん情報はありますし、正規表現パターンもたくさん出回ってますので、そう困ることはありません。
ただ「正規表現」という存在を知らないことはまずいので覚えておいてください。
正規表現の記号と意味
主な正規表現の記号と意味については以下の表の通りです。
| 記号 | 記号の説明 | 使用例 | 説明 |
| . | 任意の一文字。 改行文字は除く | b.n | banやb-n、binなどの場合該当 |
| * | 直前の1文字が0回以上発生 | ba*n | bn、ban、baanなどが該当 |
| + | 直前の1文字が1回以上発生 | ba+n | ban、baanなどが該当 |
| ^ | 行の先頭 | ^ban | 行頭にbanがある場合該当 |
| $ | 行の末尾 | ban$ | 文末にbanがある場合該当 |
| [] | カッコ内の任意の1文字と一致。 「-」で範囲指定が可能 | ①[123] ②[1-3] | 1、2、3のいずれかがある場合該当 |
| [^] | カッコ内に含まれない1文字と一致 | [^ban] | b、a、n以外の文字の場合該当 |
| {n} | 直前の文字がn回発生。 nは整数。 | ba{3}n | baaanの場合該当 |
| {n,} | 直前の文字をn回以上発生。 nは整数。 | ba{2,} | baa、baaa、baaaaなどの場合該当 |
| {n,m} | 直前の文字をn回からm回まで繰り返す。 nとmは整数。 | ba{2,4} | baa、baaa、baaaaの場合該当 |
| | | 直前もしくは直後のパターンに一致 | bn|ban | bnもしくはbanの場合該当 |
| ? | 直前の1文字が0もしくは1個のパターンに一致 | ban? | baもしくはbanの場合該当 |
| () | グループ化。()内のパターンは(グループ)と見なされる。 |
本単元の最初に書いていただいた「”^[0-9]{3}-[0-9]{4}$”」ですが
先頭の「^」は文字列の最初にマッチすることを意味します。
[0-9]は、半角数字の0から9までのいずれかにマッチするという意味です。
続く{3}は、それが3回続くという意味です。
続く「–」は、半角のハイフンそのものを意味します。
[0-9]{4}は、0から9の半角数字が4回続くという意味です。
最後の「$」は文字列の最後にマッチすることを意味します。
つまり、この正規表現パターンは、「0から9の半角数字3文字で始まり、次にハイフンがあり、0から9の半角数字4文字で終わる文字列」にマッチすることになります。
参考サイト:【5分でまるっと理解】Java正規表現についてのまとめ
参考サイト:【Java】正規表現のまとめ
下記の正規表現パターンにマッチするように文字列を設定して実行しましょう。
■電話番号
^[0-9]{2,4}-[0-9]{2,4}-[0-9]{3,4}$
■メールアドレス
^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$
Pattern
正規表現パターンで文字列を検索するには、Pattern/Matcherクラス(java.util.regexパッケージ)を利用します。
最初に文字列としてパターンを定義したあと、パターン文字列から Pattern オブジェクトを取得します。そして Pattern オブジェクトが対象の文字列とマッチするかどうか調べるのが Matcher オブジェクト( Matcher クラスのインスタンス)です。
// 検索する文字列を用意
String str = "東京都千代田区 123-4567";
// 正規表現のパターンを作成
Pattern pattern = Pattern.compile("[0-9]{3}-[0-9]{4}");
Matcher matcher = pattern.matcher(str);
正規表現のパターンオブジェクトを作るには、Patternクラスのcompileメソッドの引数に正規表現のパターンを指定します。次に、Patternクラスのmatcherメソッドの引数にパターンとマッチさせる文字列を指定してMatcherオブジェクトを作成します。
上記の例では、文字列である「東京都千代田区 123-4567」と正規表現のパターン「[0-9]{3}-[0-9]{4}」のMatcherオブジェクトを作成しています。
Matcher
実際に対象の文字列がパターンとマッチするかどうかを調べる役割をするのが Matcher オブジェクトです。これは Matcher クラス( java.util.regex.Matcher )のインスタンスです。
Matcher クラスにはコンストラクタが用意されておらず、 Pattern クラスのクラスメソッドである matcher メソッドを使ってインスタンスを取得します。
findメソッド
Matcherクラスのfindメソッドを使うことで、文字列が正規表現のパターンに一致するかをチェックすることができます。
Matcherクラスのfindメソッドは、文字列の中に正規表現のパターンが含まれる場合に”true”を返し、それ以外の場合には”false”を返します。
Patternの箇所で作成したソースに以下の一文を追記しましょう。
System.out.println(matcher.find());
trueが出力されました。
これは、文字列「東京都千代田区 123-4567」の中に、正規表現のパターン「[0-9]{3}-[0-9]{4}」が含まれているためです。
matchesメソッド
Matcher クラスの matches メソッドは対象の文字列全体がパターンにマッチするかどうかを調べます。
// 検索対象文字列
String str2 = "あいうえお";
Pattern maches = Pattern.compile(str2);
// パターン1
Matcher matches = maches.matcher("あいうえお");
System.out.println(matches.matches());
// パターン2
Matcher matches2 = maches.matcher("あいう");
System.out.println(matches2.matches());
パターン1では、文字列「あいうえお」とmatchesメソッドの引数で指定した文字列が一致しているため、「true」を返しています。
パターン2の場合、matchesメソッドの引数で指定した文字列は「あいう」で、文字列「あいうえお」と全体で一致しないため「false」が出力されます。
lookingAtメソッド
lookingAt メソッドは、対象の文字列の先頭からパターンとマッチするかどうかを調べます。先頭文字からマッチする必要はありますが、 matches メソッドのように文字列全体とマッチする必要はありません。
String str3 = "埼玉県";
Pattern samplePattern = Pattern.compile(str3);
// パターン1
Matcher m1 = samplePattern.matcher("埼玉県さいたま市");
System.out.println(m1.lookingAt());
// パターン2
Matcher m2 = samplePattern.matcher("さいたま市埼玉県");
System.out.println(m2.lookingAt());
パターン1では、文字列「埼玉県」と対象の文字列「埼玉県さいたま市」を調べて、対象の文字列の先頭からマッチしているため「true」を返します。
パターン2は対象の文字列が「さいたま市埼玉県」のため、先頭文字が「埼玉県」ではないため「false」を返します。
練習問題
「com.cmps.regex」の中に「RegexQuestion」クラスを作成してください。
問1: 文字列の先頭から4桁「0」の場合の正規表現を作成する。※「0000123456789」がOKになる
問2: 文字列が「png」、「jpg」、「jpeg」、「pdf」のいずれかの場合の正規表現を作成する。※「png」や「pdf」がOKになる
問3: 半角チェックの正規表現を作成しましょう。※全角が含まれていたらNGになる
問4: 書式チェックYYYY/MM/DDの正規表現を作成しましょう。
※「2022/12/30」がOKになる、ただし月日的に存在しないものはNGとする(4/31や2/30はNG。うるう年は考慮しなくてよい)。正規表現を29日までの月、30日までの月、31日までの月の3パターンに分けても良いです。
