正規表現の基本知識
正規表現とは
文字列をパターンで検索して、パターンにマッチするかどうかチェックする、置換する、分割するといった文字列処理を行う手法です。
パターンにマッチで利用する関数はpreg_match()です。
第1引数にパターンの文字列、第2引数に検索対象の文字列を指定する。
パターンにマッチで利用する関数はpreg_match()です。
第1引数にパターンの文字列、第2引数に検索対象の文字列を指定する。
$result = preg_match($pattern,$subject)
マッチした時1、マッチしなかったら0が戻る解析できなかったり、エラーの場合はfalseになります。
パターンは//で囲む ※##でも可
マッチした時1、マッチしなかったら0が戻る解析できなかったり、エラーの場合はfalseになります。
パターンは//で囲む ※##でも可
「46-49」が含まれているかどうか調べる
int(0) int(1)<?php
$result1 = preg_match("/46-49/u", "確か49-46でした");
$result2 = preg_match("/46-49/u", "たぶん46-49だった");
var_dump($result1);
var_dump($result2);
?>
任意の1文字を含むパターン
/4.-49/
任意の1文字が6~9の数字のパターン
/4[6-9]-49/
後置オプション(PCREパターン修飾子)
後置オプション | 説明 |
---|---|
i | アルファベットの大文字小文字を区別しない |
m | 行単位でマッチングする |
s | ドット(.)で改行文字もマッチングする |
u | パターン文字をUTF-8エンコードで扱う |
x | パターンの中の空白文字を無視する(文字パターン内の空白を除く) |
文字クラス定義[]の中で使うメタ文字
メタ文字 | 説明 |
---|---|
\ | エスケープ文字 |
^ | 否定 |
- | 文字の範囲の指定 |
文字クラスを使ったパターン
int(1) int(1) int(1) int(0) int(1)<?php
$pattern = "/[赤青緑]の玉/u";
$pattern2 = "/緑の[^玉]でした/u";
var_dump(preg_match($pattern,"それは赤の玉です"));
var_dump(preg_match($pattern,"青の玉が2個です"));
var_dump(preg_match($pattern,"緑の玉でした"));
var_dump(preg_match($pattern,"緑の箱でした"));
var_dump(preg_match($pattern2,"緑の箱でした"));
?>
定義済みの文字クラス
文字クラス | 説明 |
---|---|
\d | 数値。[0-9]と同じ |
\D | 数値以外。[^0-9]と同じ |
\s | 空白文字。[\n\r\t\x0B]と同じ |
\S | 空白文字以外。[^\s]と同じ |
\w | 英数文字、アンダースコア。[a-zA-Z_0-9]と同じ |
\W | 文字以外。[^\w]と同じ |
文字クラス[]の外で使うメタ文字
メタ文字 | 説明 |
---|---|
\ | エスケープ文字 |
^ | 先頭一致(複数行の場合は業の先頭) |
$ | 終端一致(複数行の場合は行末) |
. | 任意の1文字(改行を除く) |
[] | 文字クラスの定義 |
| | 選択肢の区切り |
() | サブパターンの囲み |
{n} | n回の繰り返し |
{n,} | n回以上の繰り返し |
{n,m} | n~m回の繰り返し |
* | {0,}の省略形(0回以上の繰り返し)/td> |
+ | {1,}の省略形(1回以上の繰り返し) |
? | {0,1}の省略形(0または1回の繰り返し) |
サブパターンの囲み
パターンを()で囲み、パターンの中にサブパターンを入れる。
携帯番号にマッチする
int(1) int(1) int(1) 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, "080-1234-5678"));
var_dump(preg_match($pattern, "07012345678"));
var_dump(preg_match($pattern, "123456789"));
?>
メタ文字をエスケープしたパターンを作る便利な関数
文字列をpreg_quote()に通すと必要な個所にエスケープの\を埋め込んでくれます。
URL等のスラッシュとピリオドをエスケープする必要がある時に便利
URL等のスラッシュとピリオドをエスケープする必要がある時に便利
URLに含まれるメタ文字をエスケープする
/https\:\/\/sample\.com\/php\//uint(1) int(0)
<?php
$escaped = preg_quote("https://sample.com/php/", "/");
$pattern = "/{$escaped}/u";
echo $pattern, "\n <br>";
var_dump(preg_match($pattern, "https://sample.com/php/です"));
var_dump(preg_match($pattern, "https://sample.com/javascript/です"));
?>
正規表現でマッチした値の取り出しと置換
preg_match()の第3引数に変数を指定すると、その変数にマッチした値が配列で入ります。
見つかった値は$matches(0)で取り出せます。
$result = preg_match($pattern,$subject,&$matches)
マッチした値は$resultに戻るのではなく、第3引数の$matchesに入ります。$resultの値は、マッチした個数、またはエラーがあった場合のfalseです。第3引数の$matchesは配列ですが、preg_match()はマッチした文字列が見つかったならそこで走査を中止するので値は1個しか入りません。見つかった値は$matches(0)で取り出せます。
マッチしたすべての要素を取り出す
$result = preg_match_all($pattern,$subject,&$matches)
implode("、",$matches[0])のように実行すると、配列から値が全て取り出され、「、」で連結された文字になる。
$result = preg_match_all($pattern,$subject,&$matches)
マッチした名前を取り出す
2人マッチしました。佐藤順子、佐々木裕子
<?php
$pattern = "/佐.+子/u";
//ヒアドキュメント
$subject = <<< "names"
佐藤由紀
佐藤順子
坂田玲子
冴島陽子
佐々木裕子
names;
$result = preg_match_all($pattern, $subject, $matches);
if ($result === false) {
echo "エラー", preg_last_error();
} else if ($result == 0) {
echo "マッチした値はありません。";
} else {
echo "{$result}人マッチしました。\n <br>";
echo implode("、", $matches[0]);
}
サブパターンの値を調べる
preg_match_all()の第3引数にマッチした値が入るが、パターン()で囲まれたサブパターンがある場合は、$第3引数[1]、$第3引数[2]、...にサブパターンでマッチした値が入ります。
正規表現を使って検索置換を行う
preg_replace()を使うことで複雑な検索置換を行うことが出来ます。
単純な文字列の検索や置換は str_replace()の方が高速に行えます。
置換後の文字は$resultに入ります。マッチした値がなかった場合は元の$subjectと同じ文字列が返り、エラーの場合はNULLが返ります。
NULLチェックはis_null()で行うことが出来ます。
単純な文字列の検索や置換は str_replace()の方が高速に行えます。
$result = preg_replace($pattern,$replacement,$subject)
第3引数の$subjectの文字列を$patternのパターンで検索し、マッチした値をすべて$replacementで置換した新しい文字を作ります。置換後の文字は$resultに入ります。マッチした値がなかった場合は元の$subjectと同じ文字列が返り、エラーの場合はNULLが返ります。
NULLチェックはis_null()で行うことが出来ます。
クレジット番号を伏字にする
1234 5678 9123 4567は次のようになります。**** **** **** **67
6566846328412597は次のようになります。
**** **** **** **97
<?php
function numbermask($subject) {
$pattern = "/^\d{4}\s?\d{4}\s?\d{4}\s?\d{2}(\d{2})$/";
$replacement = "**** **** **** **$1";
$result = preg_replace($pattern,$replacement,$subject);
if (is_null($result)) {
return "エラー:" .preg_last_error();
} else if ($result == $subject) {
return "番号エラー";
} else {
return $result;
}
}
$number1 = "1234 5678 9123 4567";
$number2 = "6566846328412597";
$num1 = numbermask($number1);
$num2 = numbermask($number2);
echo "{$number1}は次のようになります。\n <br>";
echo $num1,"\n <br>";
echo "{$number2}は次のようになります。\n <br>";
echo $num2,"\n <br>";
?>
最後の2桁をサブパターンで分ける理由は、サブパターンでマッチした値は$
1、$2、$3と順に取り出せる為です。「**** **** **$1」で置換すると最後の2桁だけが表示されて、他は伏字になる。
パターンと文字列を配列で指定する
次回は金曜日の19:30からです。<?php
$pattern = ["/開催日/u","/開始時間/u"];
$replacement = ["金曜日","19:30"];
$subject = "次回は開催日の開始時間からです。";
$result = preg_replace($pattern,$replacement,$subject);
echo $result;
?>
preg_replace()及びpreg_filter()を使えば、配列の値を正規表現を使って検索置換できます。