mb_str_replace (mb_replace)

何これ?

マルチバイト対応版の str_replace 関数です。 PHP 標準関数ではないため、サイトによって mb_str_replace、mb_replace 等と表記にゆれがありますがおそらく同じものです。

何に使うの?

日本語等(PHP が対応している言語なら何でも可)の文字列を一部置き換える場合に使います。

PHP に実装されている str_replace 関数はマルチバイト対応していないため、一部文字列が文字化けするかもしれません。 また、一部で行われている explode と join を使う方法等では思わぬところで文字が分断され、悲惨な結果になるかもしれません。

他に公開されているものとの違いは?

オリジナルの str_replace 関数は $search, $replace, $subject が配列対応していますが、 ほとんどの場所で公開されている mb_str_replace 関数は配列に対応していないようです。

ここで公開しているものは、$search, $replace, $subject の 3 引数については配列に対応していますので、 一気に置き換えることができます。 これにより、たとえば『ある文字セット(たとえば ISO-2022-JP)で使えないいわゆる機種依存文字(たとえば「㍼」「㍻」)を一般文字(たとえば「昭和」「平成」)に一気に置き換える』といったことが 1 呼び出しで行えます。

関数プロトタイプ

/**
 * マルチバイト対応 str_replace
 *
 * @param   mixed   $search     検索文字列
 * @param   mixed   $replace    置換文字列
 * @param   mixed   $subject    対象文字列
 * @param   string  $encoding   文字列のエンコーディング(省略: 内部エンコーディング)
 *
 * @return  mixed   subject 内の search を replace で置き換えた文字列
 *
 * @note    この関数は配列に対応(search, replace, subject)しています。
 */

function mb_str_replace($search, $replace, $subject, $encoding = 'auto') { ... }

引数の最後に $encoding を追加し、マルチバイト対応関数としている以外は概ね (PHP 4 の) str_replace 関数と同じです。 $search, $replace, $subject 引数はそれぞれ配列とすることができます。

PHP 5 で追加された $count には残念ながら現在のところ対応していません。 いや、$encoding があるので引数の追加位置をどうしたものかな、と。

使い方

関数を含んだファイルを require (include) して関数を呼び出すだけです。

<?php
    require_once(dirname(__FILE__) . '/mb_str_replace.function.php');
    
    $subject = '赤パジャマ青パジャマ黄パジャマ';
    $search = 'パジャマ';
    $replace = '信号';
    
    $result = mb_str_replace($search, $replace, $subject);
    var_dump($result);
?>

このサンプルの場合、「赤パジャマ青パジャマ黄パジャマ」内の「パジャマ」を「信号」に置き換えます。 つまり、赤信号青信号黄信号 となります。

※実際には、第 4 引数 ($encoding) に適切なエンコードを指定してください。 内部コードとエンコードが同一の場合は省略してもかまいません。

ライセンス

この関数は(修正済み) BSD ライセンスで提供します。 原作者表記のある限り、自由に利用いただいて結構です。

メンテナ

この関数は、HiNa がメンテナンスしていますが、動作等について保証するものではありません。 また、ライセンスは上述の通りで、利用時に報告する必要は全くありませんが一言いってもらえると大変喜びます。

なお、この関数についての連絡にはメールを送るよりも、日記のコメント機能(リンク先は初出時の日記エントリ) を利用したほうが確実に目に入ります。 メールはご他聞に漏れず、spam メールであふれています。

ダウンロード

この後の項目にソースコードがべた張りしてありますので、そちらをコピー&ペーストいただいても同じものが得られますが、どうしてもダウンロードしたい場合は、こちらをご利用ください。

ダウンロード (tar.gz / 1.02kB / SHA1SUM: a2baede0c5db1f5de3f3325e2f878cf4ee3a7ac8)

ソースコード

<?php
    // THIS FILE WRITTEN IN UTF-8, Japanese.
    
    /**
     * マルチバイト対応 str_replace
     *
     * @version     Release 2
     * @author      HiNa (hina@bouhime.com)
     * @copyright   Copyright (C) 2006-2007 by HiNa(hina@bouhime.com).
     */

    
    if(! function_exists('mb_str_replace')) {
        /**
         * マルチバイト対応 str_replace
         *
         * @param   mixed   $search     検索文字列
         * @param   mixed   $replace    置換文字列
         * @param   mixed   $subject    対象文字列
         * @param   string  $encoding   文字列のエンコーディング(省略: 内部エンコーディング)
         *
         * @return  mixed   subject 内の search を replace で置き換えた文字列
         *
         * @note    この関数は配列に対応(search, replace, subject)しています。
         */

        function mb_str_replace($search, $replace, $subject, $encoding = 'auto') {
            if(! is_array($search)) {
                $search = array($search);
            }
            if(! is_array($replace)) {
                $replace = array($replace);
            }
            if(strtolower($encoding) === 'auto') {
                $encoding = mb_internal_encoding();
            }
            if(is_array($subject)) {
                $result = array();
                foreach($subject as $key => $val) {
                    $result[$key] = mb_str_replace($search, $replace, $val, $encoding);
                }
                return $result;
            }
            
            $currentpos = 0;
            while(true) {
                $index = -1;
                $minpos = -1;
                foreach($search as $key => $find) {
                    if($find == '') {
                        continue;
                    }
                    $findpos = mb_strpos($subject, $find, $currentpos, $encoding);
                    if($findpos !== false) {
                        if($minpos < 0 || $findpos < $minpos) {
                            $minpos = $findpos;
                            $index = $key;
                        }
                    }
                }
                if($minpos < 0) {
                    break;
                }
                
                $r = array_key_exists($index, $replace) ? $replace[$index] : '';
                $subject = sprintf('%s%s%s',
                                        mb_substr($subject, 0, $minpos, $encoding),
                                        $r,
                                        mb_substr(
                                            $subject,
                                            $minpos + mb_strlen($search[$index], $encoding),
                                            mb_strlen($subject, $encoding),
                                            $encoding
                                        )
                                    );
                $currentpos = $minpos + mb_strlen($r, $encoding);
            }
            return $subject;
        }
    }
?>