ラボ > PHP:文字関連

PHPで特定の範囲内の文字列内で置き換え(preg_replace_callback())

範囲を指定して、その中で文字列を置き換えたい。

作成日:2018-02-13, 更新日:2018-02-22

基本

「preg_replace_callback()」のコールバック関数内で置き換える感じなので「preg_replace_callback(範囲, function(置き換え), 文字列)」のような感じにする。

▼ulタグ内の「<」を「<」にしたい場合。

$str = '<ul>' . "\n"
     . '<li><a href="〇〇〇">XXX</a></li>' . "\n"
     . '<li><a href="〇〇〇">XXX</a></li>' . "\n"
     . '<li><a href="〇〇〇">XXX</a></li>' . "\n"
     . '<li><a href="〇〇〇">XXX</a></li>' . "\n"
     . '<li><a href="〇〇〇">XXX</a></li>' . "\n"
     . '</ul>' . "\n"
     . '<ol>' . "\n"
     . '<li><a href="〇〇〇">XXX</a></li>' . "\n"
     . '<li><a href="〇〇〇">XXX</a></li>' . "\n"
     . '<li><a href="〇〇〇">XXX</a></li>' . "\n"
     . '<li><a href="〇〇〇">XXX</a></li>' . "\n"
     . '<li><a href="〇〇〇">XXX</a></li>' . "\n"
     . '</ol>' . "\n";

$sorce = preg_replace_callback(
   '@<ol>(.+?)<\/ol>@s',
   function ($m) {
      return str_replace('<', '&lt;', $m[0]);
   },
   $str
);

基本:改

上記で大丈夫じゃないときがある・・・。

没(2018/02/13):各scriptタグ内の「<」を「&lt;」に変換

下記だと希望通りの挙動にはなってくれないので、作り直した(2018/02/21:参照:PHP 特定のタグの中身をゴニョゴニョしたい(preg_match_all()とstr_replace())

▼内容
・「<script>」と「<script type=〇〇〇>」などを考慮・・・「<script( *| .+?)>」
・scriptタグの中身を取得したい・・・「(.+?)」
・scriptタグが複数ある場合を考慮・・・最短一致「?(<\/script>)」
・UTF8のおまじない・・・「u」
・「script」の大文字・小文字を考慮・・・「i」

$str = @file_get_contents(〇〇〇);

function parseTagsRecursive($input) {
   $regex = '/<script( *| .+?)>(.+?)?(<\/script>)/ui';
   
   if (is_array($input)) {
      $input = str_replace('<', '&lt;', $input[2]);
   }
   
   return preg_replace_callback($regex, 'parseTagsRecursive', $input);
}

$result = parseTagsRecursive($str);
echo $result;

※「PHPの公式(preg_replace_callback()の例3)に載っていたソース」をカスタマイズ。

日本語を「urlencode()」したい

・URLの日本語のトコ(全角文字・半角カナ)だけ「urlencode()」したい

function parseTagsRecursive($input) {
   $regex = '/[^\x01-\x7E]/u'; // 「1バイト文字を除く」→全角文字
   
   if (is_array($input)) {
   	$input = urlencode($input[0]);
   }
   
   return preg_replace_callback($regex, 'parseTagsRecursive', $input);
}

・URLをパースして、「urlencode()」するのがいいんだろうけど・・・クエリなどを考えると面倒だから避けたい。
・日本語ドメインは非対応。あらかじめPUNYコードに変換しておく。