文字

多字节字符串 函数

参考资料

多字节字符编码方案和他们相关的问题相当复杂,超越了本文档的范围。 关于这些话题的更多信息请参考以下 URL 和其他资源。

  • Unicode materials

    » http://www.unicode.org/

  • Japanese/Korean/Chinese 字符信息

    » http://examples.oreilly.com/cjkvinfo/doc/cjk.inf

Table of Contents

  • mb_check_encoding — 检查字符串在指定的编码里是否有效
  • mb_convert_case — 对字符串进行大小写转换
  • mb_convert_encoding — 转换字符的编码
  • mb_convert_kana — Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
  • mb_convert_variables — 转换一个或多个变量的字符编码
  • mb_decode_mimeheader — 解码 MIME 头字段中的字符串
  • mb_decode_numericentity — 根据 HTML 数字字符串解码成字符
  • mb_detect_encoding — 检测字符的编码
  • mb_detect_order — 设置/获取 字符编码的检测顺序
  • mb_encode_mimeheader — 为 MIME 头编码字符串
  • mb_encode_numericentity — Encode character to HTML numeric string reference
  • mb_encoding_aliases — Get aliases of a known encoding type
  • mb_ereg_match — Regular expression match for multibyte string
  • mb_ereg_replace_callback — Perform a regular expresssion seach and replace with multibyte support using a callback
  • mb_ereg_replace — Replace regular expression with multibyte support
  • mb_ereg_search_getpos — Returns start point for next regular expression match
  • mb_ereg_search_getregs — Retrieve the result from the last multibyte regular expression match
  • mb_ereg_search_init — Setup string and regular expression for a multibyte regular expression match
  • mb_ereg_search_pos — Returns position and length of a matched part of the multibyte regular expression for a predefined multibyte string
  • mb_ereg_search_regs — Returns the matched part of a multibyte regular expression
  • mb_ereg_search_setpos — Set start point of next regular expression match
  • mb_ereg_search — Multibyte regular expression match for predefined multibyte string
  • mb_ereg — Regular expression match with multibyte support
  • mb_eregi_replace — Replace regular expression with multibyte support ignoring case
  • mb_eregi — Regular expression match ignoring case with multibyte support
  • mb_get_info — 获取 mbstring 的内部设置
  • mb_http_input — 检测 HTTP 输入字符编码
  • mb_http_output — 设置/获取 HTTP 输出字符编码
  • mb_internal_encoding — 设置/获取内部字符编码
  • mb_language — 设置/获取当前的语言
  • mb_list_encodings — 返回所有支持编码的数组
  • mb_output_handler — 在输出缓冲中转换字符编码的回调函数
  • mb_parse_str — 解析 GET/POST/COOKIE 数据并设置全局变量
  • mb_preferred_mime_name — 获取 MIME 字符串
  • mb_regex_encoding — Set/Get character encoding for multibyte regex
  • mb_regex_set_options — Set/Get the default options for mbregex functions
  • mb_send_mail — 发送编码过的邮件
  • mb_split — 使用正则表达式分割多字节字符串
  • mb_strcut — 获取字符的一部分
  • mb_strimwidth — 获取按指定宽度截断的字符串
  • mb_stripos — 大小写不敏感地查找字符串在另一个字符串中首次出现的位置
  • mb_stristr — 大小写不敏感地查找字符串在另一个字符串里的首次出现
  • mb_strlen — 获取字符串的长度
  • mb_strpos — 查找字符串在另一个字符串中首次出现的位置
  • mb_strrchr — 查找指定字符在另一个字符串中最后一次的出现
  • mb_strrichr — 大小写不敏感地查找指定字符在另一个字符串中最后一次的出现
  • mb_strripos — 大小写不敏感地在字符串中查找一个字符串最后出现的位置
  • mb_strrpos — 查找字符串在一个字符串中最后出现的位置
  • mb_strstr — 查找字符串在另一个字符串里的首次出现
  • mb_strtolower — 使字符串小写
  • mb_strtoupper — 使字符串大写
  • mb_strwidth — 返回字符串的宽度
  • mb_substitute_character — 设置/获取替代字符
  • mb_substr_count — 统计字符串出现的次数
  • mb_substr — 获取字符串的部分

用户评论:

[#1] treilor at gmail dot com [2014-05-23 08:43:13]

A small note for those who will follow rawsrc at gmail dot com's advice: mb_split uses regular expressions, in which case it may make sense to use built-in function mb_ereg_replace.

[#2] mattr at telebody dot com [2014-05-19 07:29:07]

A brief note on Daniel Rhodes' mb_punctuation_trim().
The regular expression modifier u does not mean ungreedy, rather it means the pattern is in UTF-8 encoding. Instead the U modifier should be used to get ungreedy behavior. (I have not otherwise tested his code.)
See http://php.net/manual/en/reference.pcre.pattern.modifiers.php

[#3] Anonymous [2013-10-30 23:16:33]

Yet another single-line mb_trim() function

<?php
function mb_trim($string$trim_chars '\s'){
    return 
preg_replace('/^['.$trim_chars.']*(?U)(.*)['.$trim_chars.']*$/u''\\1',$string);
}
$string '           "some text."      ';
echo 
mb_trim($string'\s".');
//some text
?>

[#4] Daniel Rhodes [2013-09-17 13:24:27]

Here's a cheap and cheeky function to remove leading and trailing *punctuation* (or more specifically "non-word characters") from a UTF-8 string in whatever language. (At least it works well enough for Japanese and English.)


function mb_punctuation_trim($string)
{
    preg_match('/^[^\w]{0,}(.*?)[^\w]{0,}$/iu', $string, $matches); //case-'i'nsensitive and 'u'ngreedy
    
    if(count($matches) < 2)
    {
        //some strange error so just return the original input
        return $string;
    }
    
    return $matches[1];
}

Hope you like it!

[#5] Daniel Rhodes [2013-09-16 14:55:43]

Here's a cheap and cheeky function to remove leading and trailing *punctuation* (or more specifically "non-word characters") from a UTF-8 string in whatever language. (At least it works well enough for Japanese and English.)


function mb_punctuation_trim($string)
{
    preg_match('/^[^\w]{0,}(.*?)[^\w]{0,}$/iu', $string, $matches); //case-'i'nsensitive and 'u'ngreedy
    
    if(count($matches) < 2)
    {
        //some strange error so just return the original input
        return $string;
    }
    
    return $matches[1];
}

Hope you like it!

[#6] Daniel Rhodes [2013-09-16 12:11:39]

Here's a cheap and cheeky function to remove leading and trailing *punctuation* (or more specifically "non-word characters") from a UTF-8 string in whatever language. (At least it works well enough for Japanese and English.)


function mb_punctuation_trim($string)
{
    preg_match('/^[^\w]{0,}(.*?)[^\w]{0,}$/iu', $string, $matches); //case-'i'nsensitive and 'u'ngreedy
    
    if(count($matches) < 2)
    {
        //some strange error so just return the original input
        return $string;
    }
    
    return $matches[1];
}

Hope you like it!

[#7] deceze at gmail dot com [2012-09-04 10:32:56]

Please note that all the discussion about mb_str_replace in the comments is pretty pointless. str_replace works just fine with multibyte strings:

<?php

$string  
'?h???????`??';
$needle  '??';
$replace 'Foo';

echo 
str_replace($needle$replace$string);
// outputs: ?h??Foo?????`??

?>


The usual problem is that the string is evaluated as binary string, meaning PHP is not aware of encodings at all. Problems arise if you are getting a value "from outside" somewhere (database, POST request) and the encoding of the needle and the haystack is not the same. That typically means the source code is not saved in the same encoding as you are receiving "from outside". Therefore the binary representations don't match and nothing happens.

[#8] rawsrc at gmail dot com [2011-08-09 14:36:06]

Hi,

For those who are looking for mb_str_replace, here's a simple function :
<?php
function mb_str_replace($needle$replacement$haystack) {
   return 
implode($replacementmb_split($needle$haystack));
}
?>

I haven't found a simpliest way to proceed :-)

[#9] efesar [2011-01-28 14:21:13]

This small mb_trim function works for me. 

<?php
function mb_trim$string )
{
    
$string preg_replace"/(^\s+)|(\s+$)/us"""$string );
    
    return 
$string;
}
?>

[#10] johannesponader at dontspamme dot googlemail dot co [2010-10-17 09:46:19]

Please note that when migrating code to handle UTF-8 encoding, not only the functions mentioned here are useful, but also the function htmlentities() has to be changed to htmlentities($var, ENT_COMPAT, "UTF-8") or similar. I didn't scan the manual for it, but there could be some more functions that need adjustments like this.

[#11] phpnet at rcpt dot at [2010-08-19 07:46:35]

<?php

public static function mb_trim$string$chars ""$chars_array = array() )
{
    for( 
$x=0$x<iconv_strlen$chars ); $x++ ) $chars_array[] = preg_quoteiconv_substr$chars$x) );
    
$encoded_char_list implode"|"array_merge( array( "\s","\t","\n","\r""\0""\x0B" ), $chars_array ) );

    
$string mb_ereg_replace"^($encoded_char_list)*"""$string );
    
$string mb_ereg_replace"($encoded_char_list)*$"""$string );
    return 
$string;
}
?>

[#12] mt at mediamedics dot nl [2009-12-17 05:52:52]

A multibyte one-to-one alternative for the str_split function (http://php.net/manual/en/function.str-split.php):

<?php
    
function mb_str_split($string$split_length 1){
            
        
mb_internal_encoding('UTF-8'); 
        
mb_regex_encoding('UTF-8');  
        
        
$split_length = ($split_length <= 0) ? $split_length;
        
        
$mb_strlen mb_strlen($string'utf-8');
        
        
$array = array();
                
        for(
$i 0$i $mb_strlen$i $split_length){
        
            
$array[] = mb_substr($string$i$split_length); 
        }

        return 
$array;
    
    }
?>

[#13] peter AT(no spam) dezzignz dot com [2009-10-29 16:26:07]

The function trim() has not failed me so far in my multibyte applications, but in case one needs a truly multibyte function, here it is. The nice thing is that the character to remove can be whitespace or any other specified character, even a multibyte character.

<?php

// multibyte string split

function mbStringToArray ($str) {
    if (empty(
$str)) return false;
    
$len mb_strlen($str);
    
$array = array();
    for (
$i 0$i $len$i++) {
        
$array[] = mb_substr($str$i1);
        }
    return 
$array;
    }

// removes $rem at both ends

function mb_trim ($str$rem ' ') {
    if (empty(
$str)) return false;
    
// convert to array
    
$arr mbStringToArray($str);
    
$len count($arr);
    
// left side
    
for ($i 0$i $len$i++) {
        if (
$arr[$i] === $rem$arr[$i] = '';
        else break;
        }
    
// right side
    
for ($i $len-1$i >= 0$i--) {
        if (
$arr[$i] === $rem$arr[$i] = '';
        else break;
        }
    
// convert to string
    
return implode (''$arr);
    }

?>

[#14] roydukkey at roydukkey dot com [2009-10-22 21:31:00]

This would be one way to create a multibyte substr_replace function

<?php
function mb_substr_replace($output$replace$posOpen$posClose) {
        return 
mb_substr($output0$posOpen).$replace.mb_substr($output$posClose+1);
    }
?>

[#15] sakai at d4k dot net [2009-06-26 05:46:32]

I hope this mb_str_replace will work for arrays.  Please use mb_internal_encoding() beforehand, if you need to change the encoding.

Thanks to marc at ermshaus dot org for the original.

<?php

if(!function_exists('mb_str_replace')) {

    function 
mb_str_replace($search$replace$subject) {

        if(
is_array($subject)) {
            
$ret = array();
            foreach(
$subject as $key => $val) {
                
$ret[$key] = mb_str_replace($search$replace$val);
            }
            return 
$ret;
        }

        foreach((array) 
$search as $key => $s) {
            if(
$s == '') {
                continue;
            }
            
$r = !is_array($replace) ? $replace : (array_key_exists($key$replace) ? $replace[$key] : '');
            
$pos mb_strpos($subject$s);
            while(
$pos !== false) {
                
$subject mb_substr($subject0$pos) . $r mb_substr($subject$pos mb_strlen($s));
                
$pos mb_strpos($subject$s$pos mb_strlen($r));
            }
        }

        return 
$subject;

    }

}

?>

[#16] mitgath at gmail dot com [2009-04-30 06:26:06]

according to:
http://bugs.php.net/bug.php?id=21317
here's missing function

<?php
function mb_str_pad ($input$pad_length$pad_string$pad_style$encoding="UTF-8") {
   return 
str_pad($input,
strlen($input)-mb_strlen($input,$encoding)+$pad_length$pad_string$pad_style);
}
?>

[#17] Ben XO [2008-11-16 17:14:12]

PHP5 has no mb_trim(), so here's one I made. It work just as trim(), but with the added bonus of PCRE character classes (including, of course, all the useful Unicode ones such as \pZ).

Unlike other approaches that I've seen to this problem, I wanted to emulate the full functionality of trim() - in particular, the ability to customise the character list.

<?php
    

    
function mb_trim($string$charlist='\\\\s'$ltrim=true$rtrim=true)
    {
        
$both_ends $ltrim && $rtrim;

        
$char_class_inner preg_replace(
            array( 
'/[\^\-\]\\\]/S''/\\\{4}/S' ),
            array( 
'\\\\\\0''\\' ),
            
$charlist
        
);

        
$work_horse '[' $char_class_inner ']+';
        
$ltrim && $left_pattern '^' $work_horse;
        
$rtrim && $right_pattern $work_horse '$';

        if(
$both_ends)
        {
            
$pattern_middle $left_pattern '|' $right_pattern;
        }
        elseif(
$ltrim)
        {
            
$pattern_middle $left_pattern;
        }
        else
        {
            
$pattern_middle $right_pattern;
        }

        return 
preg_replace("/$pattern_middle/usSD"''$string) );
    }
?>

[#18] marc at ermshaus dot org [2008-10-03 15:05:39]

A small correction to patrick at hexane dot org's mb_str_replace function. The original function does not work as intended in case $replacement contains $needle.

<?php
function mb_str_replace($needle$replacement$haystack)
{
    
$needle_len mb_strlen($needle);
    
$replacement_len mb_strlen($replacement);
    
$pos mb_strpos($haystack$needle);
    while (
$pos !== false)
    {
        
$haystack mb_substr($haystack0$pos) . $replacement
                
mb_substr($haystack$pos $needle_len);
        
$pos mb_strpos($haystack$needle$pos $replacement_len);
    }
    return 
$haystack;
}
?>

[#19] patrick at hexane dot org [2008-06-27 08:18:44]

I wonder why there isn't a mb_str_replace().  Here's one for now:

function mb_str_replace( $needle, $replacement, $haystack ) {
  $needle_len = mb_strlen($needle);
  $pos = mb_strpos( $haystack, $needle);
  while (!($pos ===false)) {
    $front = mb_substr( $haystack, 0, $pos );
    $back  = mb_substr( $haystack, $pos + $needle_len);
    $haystack = $front.$replacement.$back;
    $pos = mb_strpos( $haystack, $needle);
  }
  return $haystack;
}

[#20] chris at maedata dot com [2007-04-24 21:50:24]

The opposite of what Eugene Murai wrote in a previous comment is true when importing/uploading a file. For instance, if you export an Excel spreadsheet using the Save As Unicode Text option, you can use the following to convert it to UTF-8 after uploading:

//Convert file to UTF-8 in case Windows mucked it up
$file = explode( "\n", mb_convert_encoding( trim( file_get_contents( $_FILES['file']['tmp_name'] ) ), 'UTF-8', 'UTF-16' ) );

[#21] mdoocy at u dot washington dot edu [2007-03-14 10:30:01]

Note that some of the multi-byte functions run in O(n) time, rather than constant time as is the case for their single-byte equivalents. This includes any functionality requiring access at a specific index, since random access is not possible in a string whose number of bytes will not necessarily match the number of characters. Affected functions include: mb_substr(), mb_strstr(), mb_strcut(), mb_strpos(), etc.

[#22] motin at demomusic dot nu [2007-01-19 17:12:41]

As peter dot albertsson at spray dot se already pointed out, overloading strlen may break code that handles binary data and relies upon strlen for bytelengths. 

The problem occurs when a file is filled with a string using fwrite in the following manner:

$len = strlen($data);
fwrite($fp, $data, $len);

fwrite takes amount of bytes as the third parameter, but mb_strlen returns the amount of characters in the string. Since multibyte characters are possibly more than one byte in length each - this will result in that the last characters of $data never gets written to the file. 

After hours of investigating why PEAR::Cache_Lite didn't work - the above is what I found. 

I made an attempt at using single byte functions, but it doesn't work. Posting here anyway in case it helps someone else:


function sb_string() {

  $arguments = func_get_args(); 

  $func_overloading = ini_get("mbstring.func_overload");

  ini_set("mbstring.func_overload", 0);

  $ret = call_user_func_array(array_shift($arguments), $arguments);

  ini_set("mbstring.func_overload", $func_overloading);

  return $ret;

}

[#23] pdezwart .at. snocap [2006-10-10 11:28:44]

If you are trying to emulate the UnicodeEncoding.Unicode.GetBytes() function in .NET, the encoding you want to use is: UCS-2LE

[#24] hayk at mail dot ru [2006-08-17 12:36:24]

Since PHP 5.1.0 and PHP 4.4.2 there is an Armenian ArmSCII-8 (ArmSCII-8, ArmSCII8, ARMSCII-8, ARMSCII8) encoding avaliable.

[#25] daniel at softel dot jp [2006-07-24 04:41:14]

Note that although "multi-byte" hints at total internationalization, the mb_ API was designed by a Japanese person to support the Japanese language.

Some of the functions, for example mb_convert_kana(), make absolutely no sense outside of a Japanese language environment.

It should perhaps be considered "lucky" if the functions work with non-Japanese multi-byte languages.

I don't mean any disrespect to the mb_ API because I'm using it everyday and I appreciate its usefulness, but maybe a better name would be the jp_ API.

[#26] Aardvark [2006-03-13 11:37:25]

Since not all hosted servces currently support the multi-byte function set, it may still be necessary to process Unicode strings using standard single byte functions.  The function at the following link - http://www.kanolife.com/escape/2006/03/php-unicode-processing.html - shows by example how to do this.  While this only covers UTF-8, the standard PHP function "iconv" allows conversion into and out of UTF-8 if strings need to be input or output in other encodings.

[#27] peter kehl [2006-03-09 08:34:36]

UTF-16LE solution for CSV for Excel by Eugene Murai works well:
$unicode_str_for_Excel = chr(255).chr(254).mb_convert_encoding( $utf8_str, 'UTF-16LE', 'UTF-8');

However, then Excel on Mac OS X doesn't identify columns properly and its puts each whole row in its own cell. In order to fix that, use TAB "\\t" character as CSV delimiter rather than comma or colon.

You may also want to use HTTP encoding header, such as
header( "Content-type: application/vnd.ms-excel; charset=UTF-16LE" );

[#28] [2005-08-14 19:24:02]

get the string octet-size, when mbstring.func_overload is set to 2 :

<?php
function str_sizeof($string) {
    return 
count(preg_split("`.`"$string)) - ;
}
?>


answering to peter albertsson, once you got your data octet-size, you can access each octet with something
$string[0] ... $string[$size-1], since the [ operator doesn't complies with multibytes strings.

[#29] peter dot albertsson at spray dot se [2005-05-21 03:43:38]

Setting mbstring.func_overload = 2 may break your applications that deal with binary data.

After having set mbstring.func_overload = 2 and  mbstring.internal_encoding = UTF-8 I can't even read a binary file and print/echo it to output without corrupting it.

[#30] nzkiwi at NOSPAMmte dot biglobe dot ne dot jp [2005-04-13 16:37:32]

A friend has pointed out that the entry 
"mbstring.http_input PHP_INI_ALL" in Table 1 on the mbstring page appears to be wrong: above Example 4 it says that "There is no way to control HTTP input character conversion from PHP script. To disable HTTP input character conversion, it has to be done in php.ini". 
Also the table shows the old-PHP-version defaults: 
;; Disable HTTP Input conversion 
mbstring.http_input = pass  *BUT* (for PHP 4.3.0 or higher) 
;; Disable HTTP Input conversion 
mbstring.encoding_translation = Off

[#31] Eugene Murai [2005-02-23 22:20:27]

PHP can input and output Unicode, but a little different from what Microsoft means: when Microsoft says "Unicode", it unexplicitly means little-endian UTF-16 with BOM(FF FE = chr(255).chr(254)), whereas PHP's "UTF-16" means big-endian with BOM. For this reason, PHP does not seem to be able to output Unicode CSV file for Microsoft Excel. Solving this problem is quite simple: just put BOM infront of UTF-16LE string.

Example:

$unicode_str_for_Excel = chr(255).chr(254).mb_convert_encoding( $utf8_str, 'UTF-16LE', 'UTF-8');

上一篇: 下一篇: