坂本研のゼミ室

PHP正規表現

正規表現とは

正規表現とは文字列をパターンで検索して、そのパターンにマッチするかチェック・置換・分割
といった文字列処理を行う手法
パターンの書き方によって、高度な文字列検索を行う事がで可能

preg_match()

パターンマッチで利用する関数
第1引数にパターンの文字列、第2引数に検索対文字列を指定して実行する
実行結果は、パターンにマッチしたら1、マッチしなかったら0、エラー時はfalseが戻る

$result = preg_match($pattern, $subject)
車のナンバー「35-10」が含まれているか調べる

調べるナンバー「35-10」を/35-10/のように/で囲んでパターンを作る
uはUTF-8を正しくマッチングするための修飾子

<?php
$result1 = preg_match("/35-10/u", "ナンバーは35-10でしたよ");
$result2 = preg_match("/35-10/u", "ナンバーは42-13でしたよ");
var_dump($result1);
var_dump($result2);
?>
出力
int(1)
int(0)
任意の1文字を含むパターン

次に調べるナンバーが「35-?0」のような場合
/35-.0/のようにする事で検索可能

<?php
$result1 = preg_match("/35-.0/u", "ナンバーは35-60でしたよ");
$result2 = preg_match("/35-.0/u", "ナンバーは36-10でしたよ");
var_dump($result1);
var_dump($result2);
?>
出力
int(1)
int(0)
任意の1文字が指定範囲のある場合

調べるナンバーが「35-?0」の?が6~9の数字である事が分かっている場合
/35-[6-9]0/とする事で検索可能

<?php
$result1 = preg_match("/35-[6-9]0/u", "ナンバーは35-60でしたよ");
$result2 = preg_match("/35-[6-9]0/u", "ナンバーは35-10でしたよ");
var_dump($result1);
var_dump($result2);
?>
出力
int(1)
int(0)
文字クラス定義の中で使うメタ文字

35-[6-9]0ので囲まれた範囲は「文字クラス」と呼ばれる
文字クラス定義の
に中で使うメタ文字は下記のものがある

\     エスケープ文字
^     否定
-     文字範囲の指定
<?php
//赤色または青色出ないときにマッチする
$pattern = "/[^赤青]色/u";
var_dump(preg_match($pattern, "赤色"));
var_dump(preg_match($pattern, "青色"));
var_dump(preg_match($pattern, "黄色"));
?>
出力
int(0)
int(0)
int(1)

ハイフンは文字の範囲を指定するので
数字は[0-9]、大文字[A-Z]、小文字[a-z]
全てのアルファベット[a-zA-Z]のようにして文字クラスを定義可能

<?php
//A1~G9にマッチする
$pattern = "/[A-G][1-9]/u";
var_dump(preg_match($pattern, "A7"));
var_dump(preg_match($pattern, "D3"));
var_dump(preg_match($pattern, "e2"));
var_dump(preg_match($pattern, "G0"));
var_dump(preg_match($pattern, "J8"));
?>
出力
int(1)
int(1)
int(0)
int(0)
int(0)
定義済みの文字クラス

使用頻度が高い文字クラスには、定義済みのものがある

文字クラス 意味
\d 数値 [0-9]と同じ
\D 数値以外 [^0-9]と同じ
\s 空白文字 [\n\r\t \x0B]と同じ
\S 空白文字以外 [^/s]
\w 英数文字、アンダースコア [a-zA-Z_0-9]
\W 文字以外 [^\w]
先頭一致と終端一致

先頭一致は[]の外で^、終端一致は$を使用する事で検索が可能

<?php
//上から始まる名前にマッチする
$pattern = "/^上/u";
var_dump(preg_match($pattern, "上田勇気"));
var_dump(preg_match($pattern, "鈴木雅夫"));
var_dump(preg_match($pattern, "山田優香"));
?>
出力
int(1)
int(0)
int(0)

同様に山で始まり子で終わる文字を指定する
また /^山..子/の.は間に2つあるので
間に2文字何も文字列でも可能となる

<?php
//山から始まり子で終わる4文字の名前にマッチする
$pattern = "/^山..子/u";
var_dump(preg_match($pattern, "上田勇気"));
var_dump(preg_match($pattern, "鈴木雅夫"));
var_dump(preg_match($pattern, "山田優子"));
?>
出力
int(0)
int(0)
int(1)
選択肢

東京または大阪などのパターンを作りたいときは|で区切る

<?php
$pattern = "/東京|大阪/u";
var_dump(preg_match($pattern, "東京タワー"));
var_dump(preg_match($pattern, "横浜駅"));
var_dump(preg_match($pattern, "ホテル大阪"));
?>
出力
int(1)
int(0)
int(1)
繰り返し

5桁の数字を検索するパターンは/[0-9][0-9][0-9][0-9][0-9]/ですが
繰り返しのメタ文字{n,m}を使用する事が可能
nは最小繰り返し数、mは最大繰り返し数となっている
{n,}のようにmを省略するとn回以上の繰り返し
{n}はn回繰り返しとなる

<?php
$pattern = "/[1-9]{3}-[1-9]{4}/u";
var_dump(preg_match($pattern, "123-4567"));
var_dump(preg_match($pattern, "12345-67"));
var_dump(preg_match($pattern, "12-34-56"));
?>
出力
int(1)
int(0)
int(0)
サブパターンで電話番号を検索する

先ほどの選択肢と同様に()で囲む事でサブパターンを作成できる

<?php
$pattern = "/(090|080|070)-{0,1}[0-9]{4}-{0,1}[0-9]{4}/u";
var_dump(preg_match($pattern, "090-1234-5678"));
var_dump(preg_match($pattern, "07098765432"));
var_dump(preg_match($pattern, "1234567"));
?>
出力
int(1)
int(1)
int(0)

さらに短く書く

<?php
$pattern = "/(090|080|070)(-?\d{4}){2}/u";
var_dump(preg_match($pattern, "090-1234-5678"));
var_dump(preg_match($pattern, "07098765432"));
var_dump(preg_match($pattern, "1234567"));
?>
出力
int(1)
int(1)
int(0)
文字クラス定義[]の外で使うメタ文字
メタ文字 説明
\ エスケープ
^ 先頭一致
$ 終端一致
. 任意の1文字(改行除く)
[] 文字クラスの定義
選択肢の区切り
() サブパターンの区切り
{n} n回の繰り返し
{n,} n回以上の繰り返し
{n,m} n~m回の繰り返し
* {0,}の省略形
+ {1,}の省略形
? {0,1}の省略形

preg_quote()

メタ文字をエスケープしたパターンを作る関数
正規表現で検索したい文字列にパターンで利用するメタ文字などが含まれている場合
preg_quote()に通すと必要な箇所にエスケープの\を埋め込んでくれる

<?php
//URLに含まれているメタ文字をエスケープする
//preg_quoteの第2引数に/を指定して/をエスケープする
$escaped = preg_quote("http://www.sample.com/php/study1/", "/");
var_dump($escaped);
?>
出力
string(41) "http\:\/\/www\.sample\.com\/php\/study1\/"