WEBデザイン・開発講義WEB Design&Development Lecture

PHPの正規表現プログラミング

PHP正規表現:PCREによるプログラミング

PHPの正規表現:PCREの特徴とプログラミング方法

PHPの正規表現プログラミング※画像クリックで拡大表示

  • PHPの正規表現の特徴は、
    1. 正規表現パターンは、デリミタで囲う必要があります。空白文字(スペース,タブ,復帰,改行,改ページ)とバックスラッシュ (¥) と nullバイトはデリミタには使用不可で、正規表現パターンにおいてデリミタ文字を使用する場合は、バックスラッシュ(¥)でエスケープします。
    2. 正規表現PCREの関数で使用するパターンの構文は、Perl言語と類似しています。
    3. 様々な修飾子を終端デリミタの後に付け、 マッチングに変化を与えることが可能です。
    4. preg_quote() 関数を使って正規表現パターンに使う文字列をエスケープ(バックスラッシュを挿入)することができます。 オプションの二番目のパラメータ(省略値:NULL)で、エスケープするデリミタも指定できます。
    5. パターン中に選択肢や繰り返しを記述できることであり、選択肢や繰り返しは、メタ文字を使ってパターン中に記述。メタ文字は、その文字自体を表わさず、正規表現の特別な解釈が行われます。
      メタ文字は、角カッコ内を除き、パターン中のどこででも使用できる文字と角カッコで括られた中でだけ使用できる文字の2種類あります。
  • PCREの正規表現のパターンは、
    文字説明
    【メタ文字】
    ¥多目的に使う一般的なエスケープ文字
    ^検索対象(複数行モードでは行)の始まりを言明
    $検索対象の終わりあるいは終端の改行文字の前(複数行モードでは行の終わり)を言明
    .改行を除くすべての文字にマッチ(デフォルト時)
    |選択枝の開始
    例:abc|def … abc又はdefの選択
    [ ]文字クラス定義の開始と終了
    例:[abc123] … abc123の文字クラス
    ¥[ 角カッコ内 ]一般的なエスケープ文字
    -[ 角カッコ内 ]文字の範囲の指定
    例:[A-Z] … 大文字アルファベット全てを表わす
    ^[ 角カッコ内 ]文字クラスの否定(最初の文字に用いた場合のみ)
    例:[^a-z] … 小文字のアルファベット以外全てを表わす
    ( )グループ化(サブパターン)の開始と終了
    【量指定子】
    ?0 又は 1 回マッチ
    (少ない回数でマッチ、'( 'の意味を拡張)
    *0 回以上の繰り返し
    +1 回以上の繰り返し
    { }最小/最大を指定する量指定子の開始と終了
    {n}ちょうど n 回のマッチ
    {n,}n 回以上のマッチ
    {n,m}n 回以上 m 回以下のマッチ
    【最短一致】
    *?0 回以上の貪欲でないマッチ
    例:123?4...文字列「124」時 '124'がマッチ
    +?1 回以上の貪欲でないマッチ
    例:123+?...文字列「124」時 マッチしない
    ??0 回又は 1 回の貪欲でないマッチ
    例:123??4...文字列「124」時 '124'がマッチ
    {n}?ちょうど n 回の貪欲でないマッチ
    {n,}?n 回以上の貪欲でないマッチ
    {n,m}?n 回以上 m 回以下の貪欲でないマッチ
    【グループ化(サブパターン)】(ptn:patternの略)
    (?:ptn)部分正規表現のグルーピング(キャプチャなし)
    (?=ptn)patternがこの位置の右側に存在する場合にマッチ(肯定の先読み)
    例:Windows (?=XP|VIST|8)… 「Windows 7」はマッチしない
    (?!ptn)patternがこの位置の右に存在しない場合にマッチ(否定先読み)
    (?<=ptn)patternがこの位置の左に存在する場合にマッチ(肯定戻り読み)
    (?>!ptn)patternがこの位置の左に存在しない場合にマッチ(否定戻り読み)
    (?>ptn)マッチ文字列に対するバックトラックを禁止する
  • PCRE正規表現の主なエスケープシーケンスは、
    文字説明
    【包括的な文字型の指定】
    ¥d10進数字
    ¥D10進数字でない文字
    ¥h水平方向の空白文字
    ¥H水平方向の空白文字でない文字
    ¥s空白文字(スペース,タブ,復帰,改行,改ページ)
    ¥S空白文字でない文字
    ¥v垂直方向の空白文字
    ¥V垂直方向の空白文字でない文字
    ¥w単語構成文字 (word character)
    ¥W非単語構成文字 (non-word character)
    【簡単な言明 (assertion) 】(文字クラス内では使用不可)
    ¥b単語境界
    ¥B非単語境界
    ¥A検索対象文字列の始端(複数行モードとは独立)
    ¥Z検索対象文字列の終端、または終端の改行(複数行モードとは独立)
    ¥z検索対象文字列の終端(複数行モードとは独立)
    ¥Gマッチングの開始位置
    【制御コードの指定】
    ¥eエスケープ文字 (x/1B/)
    ¥f改ページ(formfeed) (x/0C/)
    ¥n改行(newline) (x/0A/)
    ¥r復帰(carriage return) (x/0D/)
    ¥tタブ (x/09/)
    ¥xhh16進コードで hh の文字
    ¥ddd8進コードで ddd の文字、もしくは、後方参照
    PHP正規表現:PCREのエスケープシーケンス(PDF)
  • 修飾子は、
    修飾子説明
    全ての関数
    iパターンの中の文字は 大文字にも小文字にもマッチ
    m「行頭」および「行末」メタ文字は 対象文字列において、文字列の最初と最後に加えて、 各改行の直前と直後にそれぞれマッチ
    s改行を含む全ての文字にマッチ
    xパターンの空白文字は完全に無視。文字クラスの外にあって、かつエスケープされていない「#」と次の改行文字の間の文字も無視
    e置換文字列において後方参照に関する通常の置換を行った後、PHPコードとして評価し、検索文字列を置換するためにその結果を使用(PHP5.5で非推奨、PHP7.0で削除 )
    preg_replace関数のみ
    A(PCRE_ANCHORED)パターンは強制的に固定(anchored)となります。つまり、検索対象文字列の先頭でのみマッチするように制限されます。
    D (PCRE_DOLLAR_ENDONLY)パターン内のドルメタ文字($)は、検索対象文字列の 終わりにのみマッチします。この修飾子を設定しない場合、ドル記号は、検索対象文字列の最後の文字が改行文字であれば、その直前にもマッチします。
    S追加のパターン分析が行われます。(パターン分析は、最初の文字が単一ではなく、かつ固定でないパターンに対してのみ有用)
    U(PCRE_UNGREEDY)量指定子の「貪欲さ」が反転します。量指定子は、デフォルトで貪欲でなく、疑問符を後ろに付けてはじめて貪欲になるようになります。
    X(PCRE_EXTRA)Perl非互換なPCREの機能を有効にします。
    J(PCRE_INFO_JCHANGED)(?J)内部オプションは、ローカルのオプション PCRE_DUPNAMES の設定を変更します。サブパターンで重複した名前を使用できるようになります。
    u(PCRE_UTF8)パターンと対象文字列は、UTF-8として処理

正規表現PCREの関数と利用例

※アイコンの機能:表示   実行  ダウンロード

関数プログラム内容(事例)
preg_match 「最短一致と拡張子取得の例」
「数字英字の一致、前文字有無の一致、文字先頭と文末の一致、パターン一致」
「HTMLのドメイン形式、メールアドレスの形式チェック」
「数字、英字、文字の特殊、電話番号、メールアドレス、URLの形式チェック」
「URLとemail、郵便番号、電話番号形式チェック」
preg_match_all 「最短一致の繰り返し処理、'#'のデリミタ利用」
preg_replace 「正規表現パターンの各種操作」
「HTMLタグ削除処理」
「後方参照:URLをlinkタグ変換と日付、配列パターン、空白編集他」
preg_replace_callback 「日付の内容を指定した年に置換」
「HTMLタグ形式をユーザ関数内で編集してタグ変換」
preg_grep 「配列の添字と値の一致した配列を抽出、配列関数(array_keys array_values array_flip)を利用」
preg_split 「エスケープ文字、複数の分割パターンの文字指定」
「空白で分割、文字要素に分割、flag定数の利用」
preg_quote 正規表現文字をクオートする→「'*'をエスケープ処理するためにquoteして、斜体文字列に変換」
preg_last_error
(PHP5.2以降)
直近の PCRE正規表現処理のエラーコードを返す→「PCREエラー判断をユーザ関数利用」
preg_filter
(PHP5.3以降)
マッチした結果のみを返す→「preg_filterとpreg_replaceの違い」
preg_match関数利用
入力データチェック・ライブラリ作成と利用
入力データ形式のチェック:正規表現で形式チェックした結果「true」「false」を返すライブラリ
「入力データ形式チェック・ライブラリを利用したURL、メールアドレス、郵便番号、電話番号データの形式チェック」

  • PCREの正規表現の仕様まとめ
    PCREの正規表現の仕様まとめ(PDF)
  • サブパターン(グループ化)は、丸カッコで括られたパターンのことで、ネストも可能です。
    1. 選択肢の範囲の指定(localize)
      例えば、パターン cat(aract|erpillar|) は、単語 "cat", "cataract", "caterpillar" にマッチします。 カッコをつけないと、このパターンは、"cataract", "erpillar" または空の文字列にマッチしてしまいます。
    2. サブパターンによる値の取得(キャプチャ)
      パターン全体としてマッチに成功した場合、対象文字列の内、 サブパターンにマッチした部分の値がコールした側に返されます。 開きカッコの数が(1 から始まって)左から右に数えられ、キャプチャ用サブパターン (capturing subpattern) の番号が指定されます。($1~$99まで)
      例えば、「abc(.*)」のパターンのときの対象文字列が"abcdefg"である場合、キャプチャした値が"$1"から後方参照でき、その値は"defg"となります。
    項目説明
    サブパターン丸カッコで括られたパターン(ネスト可)「?:」サブパターン、「?!」以降のパターン否定など
    「'Sun'が後方参照2 に格納され、 後方参照1 は空」、「文字列の'Sun'と'Sat'の両方が後方参照1 に格納」の違い
  • 言明サブパターンは、対象文字列において カレントの位置の「先を読むもの」と「後ろを読むもの」の2種類あります。
    1. 先読み言明 (lookahead assertion) は、
      肯定の言明の場合「 (?= 」で始まり、 否定の言明 (negative assertion) の場合「 (?! 」で始まります。例えば、「¥w+(?=;)」は、セミコロンが後に続く単語にマッチしますが、 マッチ対象それ自体にはセミコロンは含まれません。
      また、「foo(?!bar)」は、"bar" が後ろに続かない "foo" にマッチします。 なお、一見、良く似たパターンですが「(?!foo)bar」は、"foo" 以外のものの後にある "bar" を見つけるものではないことに 注意してください。これは、どこにある "bar" とでもマッチしてしまいます。
    2. 後読み(戻り読み)言明(lookbehind assertion) は、
      肯定の言明の場合「 (?<= 」始まり、 否定の言明の場合「 (?<! 」で始まります。例えば「 (?<!str)bar」は、"str" 以外の後にある "bar" の存在を見つけるものです。
      戻り読み言明内のパターンは、それがマッチし得る文字列の長さが 固定でなければなりません。「 (?<=bullock|donkey) 」とはできますが、「 (?<!dogs?|cats?) 」という戻り読み言明は、最上位にひとつの選択肢しかなく、 その選択肢は異なる長さの文字列にマッチしうるので、不正です。
      しかし、「 (?<=abc|abde) 」のように、最上位において選択肢を 2 つ用いるように 書き換えると使用可能です。
  • 再試行無しのサブパターンは、「 (?> 」で始まる特別なカッコを用います。
    ^.*abcd$ 」と「 ^(?>.*)(?<=abcd) 」の相違は、要素「.*」 に対してバックトラックは行われず、文字列全体にのみマッチします。
    続く戻り読み言明は、最後の 4 文字に対するテストを 1 回だけ行い、テストが失敗すると、マッチはただちに失敗します。長い文字列に対しては、 この方法を用いると実行時間にかなりの差が生じます。
  • 条件付きサブパターンは、
    サブパターンを条件付きでマッチング処理させることが可能です。 言明の結果や直前のキャプチャ用サブパターンがマッチしたかどうかにより、 サブパターン中の 2 つの選択肢を選択させます。
    ・(?(条件)真パターン)
    ・(?(条件)真パターン|偽パターン)
    条件が満たされた場合、真パターンが使われます。そうでない場合は、 (もしあれば)偽パターンが使われます。
  • 再帰的パターンは、
    再帰という特殊なケースに対して専用のシーケンス (?R) が導入され(PCRE_EXTENDEDオプション設定され空白文字が無視される仮定)、「 ¥( ( (?>[^()]+) | (?R) )* ¥) 」再帰的にパターン自体に マッチする(すなわち正しくカッコで括られている)かする部分文字列に 何回でもマッチします。最後に閉じカッコにマッチします。
    ・再帰的パターンの例:→

PHP正規表現の補足説明

PHPリファレンス

参考資料の表示

推奨参考図書

pagetopへ