2022/03/05
PHP における正規表現は電話番号を判定したり、メールアドレスが正しいか確認したり様々なところで活躍します。
割とよく使う正規表現ですが、記述するときに毎回、書式を忘れてしまうんですよね。。
今回は備忘録として PHP における正規表現についてエントリーします。
INDEX
1)正規表現でエスケープが必要な文字
正規表現でエスケープが必要な文字は、いわゆるメタ文字になります。
その文字本来の意味とは異なり、プログラムで特別な意味を持たせた文字のこと。
例えば、正規表現では「+」は "足す" ではなく1回以上の連続文字を意味するメタ文字になります。
メタ文字 | 説明 |
---|---|
\ | 多目的に使う一般的なエスケープ文字 |
^ | 検索対象の始まりを言明 |
$ | 検索対象の終わりあるいは終端の改行文字の前を言明 |
. | 改行を除くすべての文字にマッチ(デフォルト時) |
[ | 文字クラス定義の開始 |
] | 文字クラス定義の終了 |
| | 選択肢の開始 |
( | サブパターンの開始 |
) | サブパターンの終了 |
? | 0 または 1 回マッチ |
* | 0 回以上の繰り返し |
+ | 1 回以上の繰り返し |
{ | 最小/最大を指定する量指定子の開始 |
} | 最小/最大を指定する量指定子の終了 |
特殊な役割を持つため、正規表現の検索文字として使用する場合はメタ文字ではないことを示すためにバックスラッシュを使用してエスケープ処理をします。
エスケープが必要なメタ文字は以下になります。
2)文字クラスについて
[ ] で囲まれた部分を文字クラスと呼びます。
文字クラスでマッチするのは、あくまで1文字だけです。
基本形
囲まれた文字のどれか1文字にマッチする表現となります。
# a、b、c、d、e、f、g の何れかの文字にマッチする
[abcdefg]
一括
[ ] の中で、- を使うと範囲を表すことができます。
# 0、1、2、3、4、5、6、7、8、9 の何れかの1文字にマッチする
[0-9]
# 0~9、a ~ z、A ~ Z のいずれか1文字にマッチする
[a-zA-Z0-9]
否定
文字クラスの中で ^(キャレット)を使うと否定になる。
# 数字以外の1文字にマッチする
[^0-9]
応用(ハイフンマイナスや空白も含める)
文字クラス内でハイフンマイナス自体を表すには、\^
のようにバックスラッシュでエスケープする方法があります。
ほかに、以下のように文字クラスの冒頭または末尾に置くこともできます。
# 小文字の a から z と、大文字の A から Z の文字+ハイフンマイナス
[a-zA-Z\-]
# もしくは
[-a-zA-Z]
[a-zA-Z-]
# 小文字の a から z と、大文字の A から Z の文字+空白文字
[a-zA-Z0-9\s]
3)量指定子について
量指定子と呼ばれるものが4つあります。
これはその前の要素を何個繰り返すか?という指定になります。
1)?
「?」は直前の要素が0個か1個の場合にマッチします。
# 直前の s に対してマッチするので http か https がマッチ対象となる
https?
2)*
「*」は直前の要素が0個以上繰り返し存在する場合にマッチします。
# o に対してマッチしようとするので、god や gd や good がマッチする。
go*d
3)+
「+」は直前の要素が1個以上繰り返し存在する場合にマッチします。
# o という文字が1個以上連続する場合なので god や good や gooood にマッチします。
o+
4){n} {n,} {m,n}
直前の要素の繰り返しの数を指定します。
# a が 5 個繰り返されるので、aaaaa にマッチする。
a{5}
# a や aa や aaa にマッチする。
a{1,3}
# a が 1 以上繰り返されるものにマッチする。
a{1,}
4)選択にまつわる正規表現
正規表現における()は2つの役割があります。
1)他の正規表現の一部として利用する
2)正規表現の有効範囲を指定する機能
1)他の正規表現の一部として利用する
以下は red手袋、white手袋、yellow手袋のいずれかにマッチします。
「|」は複数の選択肢のいずれかにマッチさせる場合に利用します。
# ここにおける () は、手袋という他の正規表現との一部として機能している。
(red|white|yellow)手袋
2)正規表現の有効範囲を指定する機能
以下は php か phpman のいずれかにヒットします。
man を一括りにした正規表現としてあらわしており、これをグループ化と呼びます。
php(man)?
5)位置にまつわる正規表現
位置を指定する正規表現もいくつかあります。
^
「^」は文字列の行頭(例だと "cat")にマッチします。ポイントとしては、マッチするのは先頭の文字ではなく("c" ではない)行頭("cat")ということです。
# category や cat1 にはマッチするが、tomcatにはマッチしない。
^cat
$
「$」は文字列の末尾にマッチする
6)PHPがサポートしている正規表現
PCREとPOSIXについて
PHPには大きく2種類の正規表現エンジンが用意されています。
1つは Perl 互換の PCRE、もう1つは POSIX 拡張です。
PCRE正規表現を扱う関数は preg で始まります。
$subject = '私はリンゴが好きです';
$search = '/リンゴ/';
$replace = 'バナナ';
$subject = preg_replace($search, $replace, $subject);
// 実行結果:私はバナナが好きです。
echo $subject;
POSIX 拡張正規表現を扱う関数は ereg で始まります。
ereg 系の関数はバイナリセーフではないため、セキュリティの観点からもおススメできず、PHP5.3以降では原則非推奨となっています。
$string = "This is a test";
// 実行結果:This was a test
echo ereg_replace(" is", " was", $string);
文字コードの問題
基本はPHPにおいて正規表現を処理するのは preg 系です。
ですが、preg 系で処理できるのは UTF-8 だけです。
SJIS や EUC-JP などの文字コードで記載しているマルチバイト文字列を処理したい場合は mb_ereg 系を使います。
6)PHPでの正規表現の使い方
PCRE正規表現を扱うための構文を紹介します。
デミリタ
記述したパターンはデミリタ(区切り文字)で囲む必要があります。
一般的には /(スラッシュ)を利用します。
preg_match 関数
PHP における preg_match 関数では、ある文字列から正規表現で指定したパターンにマッチした文字列を検索することができます。
構文
第二引数:パターンマッチの対象となる文字列を指定する
・マッチした場合、1を返します。
・マッチしなかった場合、0を返します。
・第三引数は配列で検索結果が入ります。
実例
### 文字列 "BC" を指定
echo preg_match("/BC/", "ABC"); // 1 マッチする
echo preg_match("/BC/", "ACB"); // 0 マッチしない
### 「A」または「B」を指定
echo preg_match("/[AB]/", "ABC"); // 1 マッチする
echo preg_match("/[AB]/" "ZZB"); // 1 マッチする
echo preg_match("/[AB]/" "ZZZ"); // 0 マッチしない
### 「A」以外の文字を指定
echo preg_match("/[^A]/", "ZZZ"); // 1 マッチする
echo preg_match("/[^A]/", "ZAA"); // 1 マッチする
echo preg_match("/[^A]/", "AAA"); // 0 マッチしない
### 「A」または「B」または「C」の文字を指定
echo preg_match("/[A-C]/", "ABC"); // 1 マッチする
echo preg_match("/[A-C]/", "ZZC"); // 1 マッチする
echo preg_match("/[A-C]/", "ZZZ"); // 0 マッチしない
### 先頭が「ZX」の文字を指定
echo preg_match("/^ZX/", "ZXC"); // 1 マッチする
echo preg_match("/^ZX/", "AZX"); // 0 マッチしない
### 末尾が「TK」の文字を指定
echo preg_match("/TK$/", "ZTK"); // 1 マッチする
echo preg_match("/TK$/", "TKZ"); // 0 マッチしない
### 連続する文字を指定
echo preg_match("/c{2}/", "acccb"); // 1 マッチする
echo preg_match("/c{2}/", "accb"); // 1 マッチする
echo preg_match("/c{2}/", "acbc"); // 0 マッチしない
### 数値1桁以上とハイフン ( - ) を指定
echo preg_match("/[0-9]{1,}-/", "1-"); // 1 マッチする
echo preg_match("/[0-9]{1,}-/", "123-"); // 1 マッチする
echo preg_match("/[0-9]{1,}-/", "ab1-"); // 1 マッチする
echo preg_match("/[0-9]{1,}-/", "a1b-"); // 0 マッチしない
### 数値 ( 0-9 ) の5桁 + 先頭と末尾も ( 0-9 )
echo preg_match("/^[0-9]{5}$/", "12345"); // 1 マッチする
echo preg_match("/^[0-9]{5}$/", "a2345"); // 0 マッチしない(文字あり)
echo preg_match("/^[0-9]{5}$/", "123456"); // 0 マッチしない(桁があわない)
### 数値 ( 0-9 ) と英字 (a-f ) の5桁+先頭と末尾も ( 0-9 or a-f )
echo preg_match("/^[0-9a-f]/{5}", "1a23b"); // 1 マッチする
echo preg_match("/^[0-9a-f]/{5}", "a1bc"); // 0 マッチしない 桁数不足
echo preg_match("/^[0-9a-f]/{5}", "12345"); // 1 マッチする 数値のみ
echo preg_match("/^[0-9a-f]/{5}", "abcde"); // 1 マッチする 英字のみ
### 郵便番号 ( 数値 3 桁とハイフンと数値 4 桁 ) + 先頭と末尾も ( 0-9 )
echo preg_match("/^[0-9]{3}-[0-9]{4}$/", "123-4567"); // 1 マッチする
echo preg_match("/^[0-9]{3}-[0-9]{4}$/", "1234567"); // 0 マッチしない
echo preg_match("/^[0-9]{3}-[0-9]{4}$/", "1234-567"); // 0 マッチしない
### ドット ( . ) を文字として指定 ( エスケープ )
echo preg_match("/a\./", "a."); // 1 マッチする
echo preg_match("/a\./", "aa"); // 0 マッチしない
preg_replace 関数
PHP における preg_replace 関数は、正規表現で検索して文字列を置き換えるための関数です。
構文
第二引数:置換後の文字列を指定する。※区切り文字 / などは不要。
第三引数:パターンマッチの対象となる文字列を指定する。
実例
### 正規表現「あ」または「う」
echo preg_replace("/[あう]/u", "a", "あいうーあいう");
// 出力結果:aいaーaいa
パターン修飾子
オプション | 説明 |
---|---|
i | 大文字も小文字もマッチする |
u | 対象文字列をUTF-8として扱う |
以上です。
仕事で Laravel を使っています。気づいたことや新しい発見など情報を発信していきます。問い合わせはこちら。