質問

私が実行している文字列交換が多バイト安全であることを確認したいと思います。ネットの周りでいくつかのMB_STR_REPLACE機能が機能していることがわかりましたが、それらは遅いです。 500〜900バイトを通過した後、20%増加していると話しています。

推奨事項はありますか? preg_replaceはネイティブでコンパイルされているので、より速くなる可能性があるので、私は考えています。どんな考えも感謝しています。

役に立ちましたか?

解決

言われるように そこの, 、STR_REPLACEは、すべてのパラメーターがUTF-8有効である限り、UTF-8コンテキストで安全に使用できます。入力の妥当性を確認すると、別の機能を探す必要はありません。

他のヒント

エンコーディングは、どこからでも入力がある場合(UTF8など)、マルチバイトセーフ関数のみを使用することを好みます。にとって str_replace, 、 使ってます これです これは十分に速いです。

if (!function_exists('mb_str_replace'))
{
   function mb_str_replace($search, $replace, $subject, &$count = 0)
   {
      if (!is_array($subject))
      {
         $searches = is_array($search) ? array_values($search) : array($search);
         $replacements = is_array($replace) ? array_values($replace) : array($replace);
         $replacements = array_pad($replacements, count($searches), '');
         foreach ($searches as $key => $search)
         {
            $parts = mb_split(preg_quote($search), $subject);
            $count += count($parts) - 1;
            $subject = implode($replacements[$key], $parts);
         }
      }
      else
      {
         foreach ($subject as $key => $value)
         {
            $subject[$key] = mb_str_replace($search, $replace, $value, $count);
         }
      }
      return $subject;
   }
}

これが私の実装です アランの答え:

/**
 * Replace all occurrences of the search string with the replacement string. Multibyte safe.
 *
 * @param string|array $search The value being searched for, otherwise known as the needle. An array may be used to designate multiple needles.
 * @param string|array $replace The replacement value that replaces found search values. An array may be used to designate multiple replacements.
 * @param string|array $subject The string or array being searched and replaced on, otherwise known as the haystack.
 *                              If subject is an array, then the search and replace is performed with every entry of subject, and the return value is an array as well.
 * @param string $encoding The encoding parameter is the character encoding. If it is omitted, the internal character encoding value will be used.
 * @param int $count If passed, this will be set to the number of replacements performed.
 * @return array|string
 */
public static function mbReplace($search, $replace, $subject, $encoding = 'auto', &$count=0) {
    if(!is_array($subject)) {
        $searches = is_array($search) ? array_values($search) : [$search];
        $replacements = is_array($replace) ? array_values($replace) : [$replace];
        $replacements = array_pad($replacements, count($searches), '');
        foreach($searches as $key => $search) {
            $replace = $replacements[$key];
            $search_len = mb_strlen($search, $encoding);

            $sb = [];
            while(($offset = mb_strpos($subject, $search, 0, $encoding)) !== false) {
                $sb[] = mb_substr($subject, 0, $offset, $encoding);
                $subject = mb_substr($subject, $offset + $search_len, null, $encoding);
                ++$count;
            }
            $sb[] = $subject;
            $subject = implode($replace, $sb);
        }
    } else {
        foreach($subject as $key => $value) {
            $subject[$key] = self::mbReplace($search, $replace, $value, $encoding, $count);
        }
    }
    return $subject;
}

彼はキャラクターのエンコードを受け入れませんが、あなたはそれを介してそれを設定できると思います mb_regex_encoding.

私のユニットテストが合格します:

function testMbReplace() {
    $this->assertSame('bbb',Str::mbReplace('a','b','aaa','auto',$count1));
    $this->assertSame(3,$count1);
    $this->assertSame('ccc',Str::mbReplace(['a','b'],['b','c'],'aaa','auto',$count2));
    $this->assertSame(6,$count2);
    $this->assertSame("\xbf\x5c\x27",Str::mbReplace("\x27","\x5c\x27","\xbf\x27",'iso-8859-1'));
    $this->assertSame("\xbf\x27",Str::mbReplace("\x27","\x5c\x27","\xbf\x27",'gbk'));
}

上位のメモ http://php.net/manual/en/ref.mbstring.php#109937 言う str_replace マルチバイト文字列で動作します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top