PHP

【PHP】正規表現メモ

いつまで経っても正規表現が覚えられないので、整理してみました。

正規表現については他言語と共通な部分もあるかと思いますが、基本PHP前提です。

1. 検索関数、置換関数の使い方

単純な文字列ではなく、あるパターンに当てはまる文字を検索したり、置換したい場合に、下記関数とセットで正規表現を使用します。

文字列検索 (preg_match関数) ※1個だけ検索

//構文
preg_match( $pattern, $str, $matches);

// ABCから始まる文字列を検索
preg_match('/^ABC.+$/', 'ABCDE', $matches);

var_dump($matches);
//array (
//    [0]=>"ABCDE",
//)

echo $matches[0]; //ABCDE

$patternについて
$patternは/(スラッシュ)で囲みます
/で囲まれた部分が正規表現(パターン)になります
2番目の/の後にパターン修飾子(オプション)を指定できます。なくてもOK。

'/パターン/パターン修飾子'

文字列検索 (preg_match_all関数) ※すべて検索

//構文
preg_match_all( $pattern, $str, $matches);

// 複数行の文字列に対して、ABCから始まる文字列を"全て"検索
$str = "ABCDE
ABCFGH
IJKLMN";
preg_match_all('/^ABC.+$/m', $str, $matches);

var_dump($matches);
//array (
//    [0]=>array (
//        [0]=>"ABCDE",
//        [1]=>"ABCFGH",
//    ),
//)

echo $matches[0][0]; //ABCDE
echo $matches[0][1]; //ABCFGH

文字列置換 (preg_replace関数)

//構文
preg_replace($pattern, $replace, $str);

// ABCから始まる文字列をFGHに置換する
echo preg_replace('/^ABC.+$/', 'FGH', 'ABCDE'); //FGH

2. パターン修飾子(オプション)

修飾子 意味
なし 1行目の文字列だけ対象とする。
i 小文字大文字を区別しない。
m 複数行の文字列として扱う。 ※行ごとに処理したい場合などに指定
s 改行を無視して1行の文字列とみなす。
※改行があるhtml要素を処理したい場合などに指定
u UTF-8として処理する。 ※日本語を処理したい場合などに指定

3. 文字の意味

正規表現には一つの文字で複数の意味を表すものがあります。
すべてではありませんが、よく使うものをぱっと見ですぐわかるようにまとめました。
太字は大まかな意味。

文字 意味① 意味②
[] 文字クラス。[ ]内のいずれかの1文字。
[abc] (aかbかcに一致)
[a-z] (小文字アルファベット1文字に一致)
[0-9] (数字1桁に一致)
^ 位置指定。直後の文字列から始まる
例) ^abc (abcから始まるabcに一致)
文字クラス否定。角括弧の中で直後の文字を否定。
例) [^abc] (aかbかc以外の文字列に一致)
$ 位置指定。直前の文字列で終わる。
例) abc$ (末尾がabcで終わるabcに一致)
. 任意の文字。任意の1文字。
? 繰り返し。直前の文字が0または1文字。
例) @? (@があってもなくても一致)
最短マッチ。繰り返し文字とセットで指定する。詳しくは下記 5-1. 最短マッチ(最短一致)で解説。
* 繰り返し。直前の文字を0個以上繰り返し。
例) .* (0文字以上の任意の文字列に一致)
+ 繰り返し。直前の文字を1個以上繰り返し。
例) .+ (1文字以上の任意の文字列に一致)
{n} 繰り返し。直前の文字をn個繰り返し。
例) [0-9]{3} (3桁の数字に一致)
{n,} 繰り返し。直前の文字をn個以上繰り返し。
例) [0-9]{3,} (3桁以上の数字に一致)
{,n} 繰り返し。直前の文字をn個以上繰り返し。
例) [0-9]{,3} (3桁以下の数字に一致)
{n,m} 繰り返し。直前の文字をn〜m個繰り返し。
例) [0-9]{1,3} (1〜3桁の数字に一致)
() グループ化。範囲の限定。
例) (abc)+ (abcを繰り返す文字列に一致)
キャプチャグループ。()で囲んだパターンを後方で取得する。詳しくは下記 5-2. キャプチャグループ
\ エスケープ文字。後に続く、特別な意味を持つ文字をただの文字列にする。

例) \/ (「/」文字列に一致)
エスケープシーケンス。後に続く文字と一緒にキーボードから入力できない特殊な文字を意味する。下記 4. エスケープシーケンスに一覧記載。
例) \n (改行に一致)
| 条件式。または。
例) A|B (AまたはBに一致)

4. エスケープシーケンス

\(バックスラッシュ)と、後に続く文字とセットで、キーボードから入力できない特殊な文字を意味します。PCの規定であらかじめ決められています。

文字 意味
\n 改行
\t タブ
\d 数字 ※[0-9]と同義
\D 数字以外の文字 ※[^0-9]と同義
\s 空白文字 (半角スペース、全角スペース、タブ、改行、改ページ含む)
\S 空白以外の文字

5. 解説が必要な項目

5-1. 最短マッチ(最短一致)

"?"は最短マッチを意味します。言葉で説明するより例を見た方が理解が早いのでさっそく。

クラス名がtestのdiv要素を、閉じタグまで取得したい

$str = '<div><div class="test">テスト</div></div>';

// ?をつけない (デフォルトでは最長マッチ)
$pattern = '/<div class="test">.+<\/div>/';
if ( preg_match($pattern, $str, $matches) ) {
    echo htmlspecialchars($matches[0]); //<div class="text">テスト</div></div>
}

// ?をつける (最短マッチ)
$pattern = '/<div class="test">.+?<\/div>/';
if ( preg_match($pattern, $str, $matches) ) {
    echo htmlspecialchars($matches[0]); //<div class="text">テスト</div>
}

.+に?を加えることで、後に続く</div>を最短で切り上げてマッチさせることができます。

最短マッチの?は、繰り返しを意味する文字(量指定子)の後に指定します。
「*」、「+」、「{n,m}」など文字ですね。

最短マッチは結構使うので覚えておくと便利

5-2. キャプチャグループ

パターンに一致する文字列を検索し、そこから部分的に文字列を取得したい時があります。
その部分的な文字列を()で囲んだものをキャプチャグループと呼びます。
キャプチャグループは後方(今回だと$matches)で取得できます。

http://abc/から"abc"だけを取得したい

$str = 'http://abc/';
$pattern = '/^http:\/\/(.+)\/$/'; // "http://"で始まり"/"で終わる文字列をマッチさせる
preg_match($pattern, $str, $matches);

var_dump($matches);
//array (
//    [0]=>"http://abc/",
//    [1]=>"abc",
//)

preg_matchは全体マッチした文字列が$matches[0]に入り、キャプチャグループで指定した文字列が$matches[1]以降に代入されます。

キャプチャグループが複数ある場合、前から順番に$matches[1]、$matches[2]と値が代入されます。

これがpreg_match_all関数だとまた違った値代入になりますが、それは別途書こうと思います。

-PHP
-,

© 2022 EgTips Powered by AFFINGER5