PHPでの正規表現の実用例

正規表現を扱えるようになると色々便利になるんですが、基礎の部分だけ学んでも実際に使う時には結局どうすればいいのか分からないことが多いです。

なので今回は、私がこれまでに正規表現を活用して処理を加えた具体例をいくつか紹介していこうかなと思います。

了のアイコン画像

新しいパターンに遭遇すれば、随時更新していく予定です。

基礎的な細かい部分は説明しませんので、ググってね。

目次

例1:class='~'class="~"に統一させる

これを使うことは個人的にはほぼないですが、以下で紹介していく例でclassの置換などをしていくにあたって、属性値の指定を'で囲むのか"で囲むのかが定まっていない場合はそれを考慮した書き方をしなくてはなりません。

ただ、それだと一気に書き方が複雑になるので、「その前に全部統一させておこう」というのがこの例です。

※ 本来であればどちらかで統一して書くようにしてコーディングを行います。WordPressはで出力される属性は基本的に"で囲まれているので、以下では"で囲まれている前提で話をしていきます。

実際の置換コードはこんな感じ

$pattern = '/class=\'(.*?)\'/';
$replace = 'class="$1"';
$content  = preg_replace( $pattern, $replace, $content );

(.*?)というのは最短マッチと呼ばれるものですが、ちゃんと知らずに使うと大変なことになったりするので、一応以下のサイトなどは目を通しておくべきかなと思います。

参考:[正規表現] .*?は最短マッチではない

$patternは最短マッチを使わずに以下のようにしてもOKです。

$pattern = '/class=\'([^\']*)\'/';

([^\']*)とは、「'以外の文字列が0文字以上続く部分」のこと。

こっちの方が無難かも。

例2:特定のタグで、とあるクラス名を別のクラス名に置換する

たとえば、aタグについているoldクラスをnewというクラスに置換する場合

$pattern = '/<a([^>]*)class="old"/';
$replace = '<a$1class="new"';
$content  = preg_replace( $pattern, $replace, $content );

<a ~ class=までの間にhref属性などの他の属性値があったとしても、それを壊さないようにしています。

[^>]*は「>以外の文字列が0文字以上続く部分」にマッチする。

これを最短マッチの(.*?)とか使っちゃうと、oldというクラスを持つ他のタグ(例えばspan)が、普通のaタグとoldクラスを持つaタグの間に入っている場合に、spanタグのクラスの方が置換されてしまうので注意。

他にもクラスを持っている可能性がある場合

上記は単純にoldというクラスを1つだけ持っていることを想定したケース。

それだけでなく、"hoge old""old foo""hoge old foo"のようなクラスを持つ可能性がある場合は以下のようにする。

$pattern = '/<a([^>]*)class="([^"]*)old/';
$replace = '<a$1class="$2new';
$content  = preg_replace( $pattern, $replace, $content );

class属性の値を囲んでいるのが"'のどちらもあり得る場合

例1の方法で、あらかじめ"に統一してから上記のコードを書くという方法が一番見返した時にわかりやすいかなと思います。

一度のpreg_replace()ですませたい!という人は、以下のようにしてもいいでしょう。(もっといいのあるかも)

$pattern = '/<a([^>]*)class=["\']([^"\']*)old([^"\']*)["\']/';
$replace = '<a$1class="$2new$3"';
$content  = preg_replace( $pattern, $replace, $content );

例3:imgタグにlazyloadクラスをつけてsrc属性をdata-src属性に変換

WordPressの記事内の画像をlazysizesを使って遅延読み込みに対応させるケースで使っています。

・すでにclassを持つかどうか
・その中にlazyloadというクラス名がすでについているかどうか

などを考慮する必要があります。

$content = preg_replace_callback('/<img([^>]*)>/', function( $matches ) {
  $match = rtrim ( $matches[1], '/' );
  //classを持っているかどうか
  if ( strpos( $match, 'class=' ) !== false ) {

    //まだ'lazyload'クラスを持っていなければ追加
    if ( strpos( $match, 'lazyload' ) === false ) {
      $match = preg_replace('/class="([^"]*)"/', 'class="$1 lazyload"', $match);
    }

  } else {
    //classがなければ、classごと追加
    $match .= 'class="lazyload" ';
  }

  //src属性をdata-srcへ
  $match = str_replace(' src=', ' data-src=', $match);

  return '<img'. $match .'>';
}, $content);

この例では、imgタグの中身( <img~>)をpreg_replace_callback()で取得してから、その中でさらにclassなどの書き換えを行なっています。

このように、特定のタグの属性値を複数書き換えたり条件分岐を挟みたい時は、preg_replace_callback()を使うと便利です。

src属性をdata-srcへ変換する時、プレースホルダー画像をsrcとして残したりしてもいいでしょう。

例4:特定のタグを別のタグで囲む

例:tableタグをdivタグで囲む

$pattern = '/<table(.*?)<\/table>/s';
$replace = '<div><table$1</table></div>';
$content  = preg_replace( $pattern, $replace, $content );
return $content;

パターン修飾子sを使っています。(改行が含まれていてもマッチできるやつ)

一応紹介しましたが、要素をラップするのはJavaScriptでやってしまった方が色々と楽かなとは思います。

例5:テキストの中のURL部分をリンク化する

ほげほげhttps://wemo.tech/tips/2160ほげほげ

のようになっているテキストで、「https://wemo.tech/tips/2160」の部分をそのURLへのリンクにするコードも、正規表現で実現できます。

$pattern = '/((?:https?|ftp):\/\/[-_.!~*\'()a-zA-Z0-9;\/?:@&=+$,%#]+)/';
$replace = '<a href="$1">$1</a>';
$content = preg_replace( $pattern, $replace, $content );

この記事が気に入ったら
フォローしてね!

コメント

コメントする

目次
閉じる