mb_substr
Корректно выполняет substr() для многобайтовых кодировок, учитывая количество символов. Позиция отсчитывается от начала string . Позиция первого символа — 0, второго — 1 и т.д.
Список параметров
Исходная строка для получения подстроки.
Если start неотрицательный, возвращённая строка начнётся с позиции start от начала строки string , начальный символ имеет индекс 0. К примеру, в строке ‘ abcdef ‘, символ в позиции 0 — это ‘ a ‘, символ в позиции 2 — ‘ c ‘ и т.д.
Если start отрицательный, возвращаемая строка начнётся отсчитывая start символов с конца string .
Максимальное количество символов возвращаемой из string подстроки. Если не указан или равен NULL — извлекаются все символы до конца строки.
Параметр encoding представляет собой символьную кодировку. Если он опущен или равен null , вместо него будет использовано значение внутренней кодировки.
Возвращаемые значения
mb_substr() возвращает часть строки string , заданную параметрами start и length .
Список изменений
Смотрите также
User Contributed Notes 8 notes
As you often need to iterate over UTF-8 characters inside a string, you might be tempted to use mb_substr($text,$i,1).
The problem with this is that there is no «magic» way to find $i-th character inside UTF-8 string, other than reading it byte by byte from the begining. Thus a loop which calls mb_substr($text,$i,1) N times for all possible N values of $i, will take much longer than expected. The larger the $i gets, the longer is the search for $i-th letter. As characters are between 1 to 6 bytes long, one can convince oneself, that the execution time of such loop is actually Theta(N^2), which can be really slow even for moderately long texts.
One way to work around it is to first split your text into an array of letters using some smart preprocessing, and only then iterate over the array.
Here is the idea:
class Strings
public static function len ( $a ) return mb_strlen ( $a , ‘UTF-8’ );
>
public static function charAt ( $a , $i ) return self :: substr ( $a , $i , 1 );
>
public static function substr ( $a , $x , $y = null ) if( $y === NULL ) $y = self :: len ( $a );
>
return mb_substr ( $a , $x , $y , ‘UTF-8’ );
>
public static function letters ( $a ) $len = self :: len ( $a );
if( $len == 0 ) return array();
>else if( $len == 1 ) return array( $a );
>else return Arrays :: concat (
self :: letters ( self :: substr ( $a , 0 , $len >> 1 )),
self :: letters ( self :: substr ( $a , $len >> 1 ))
);
>
>
?>
As you can see, the Strings::letters($text) split the text recursively into two parts. Each level of the recursion requires time linear in the length of the string, and there is logarithmic number of levels, so the total runtime is O(N log N), which is still more than theoretically optimal O(N), but sadly this is the best idea I’ve got.
Note: If borders are out of string — mb_string() returns empty _string_, when function substr() returns _boolean_ false in this case.
Keep this in mind when using «== default»>
var_dump ( substr ( ‘abc’ , 5 , 2 ) ); // returns «false»
var_dump ( mb_substr ( ‘abc’ , 5 , 2 ) ); // returns «»
?>
It’s especially confusing when using mbstring with function overloading turned on.
Thanks Darien from /freenode #php for the following example (a little bit changed).
It just prints the 6th character of $string.
You can replace the digits by the same in japanese, chinese or whatever language to make a test, it works perfect.
mb_internal_encoding ( «UTF-8» );
$string = «0123456789» ;
$mystring = mb_substr ( $string , 5 , 1 );
echo $mystring ;
?>
(I couldn’t replace 0123456789 by chinese numbers for example here, because it’s automatically converted into latin digits on this website, look :
零一二三四
五六七八九)
I’m trying to capitalize only the first character of the string and tried some of the examples above but they didn’t work. It seems mb_substr() cannot calculate the length of the string in multi-byte encoding (UTF-8) and it should be set explicitly. Here is the corrected version:
function mb_ucfirst ( $str , $enc = ‘utf-8’ ) <
return mb_strtoupper ( mb_substr ( $str , 0 , 1 , $enc ), $enc ). mb_substr ( $str , 1 , mb_strlen ( $str , $enc ), $enc );
>
?>
cheers!
quick and dirty loop through multibyte string
function get_character_classes ( $string , $encoding = «UTF-8» ) $current_encoding = mb_internal_encoding ();
mb_internal_encoding ( $encoding );
$has = array();
$stringlength = mb_strlen ( $string , $encoding );
for ( $i = 0 ; $i < $stringlength ; $i ++) $c = mb_substr ( $string , $i , 1 );
if (( $c >= «0» ) && ( $c <= "9" )) $has [ 'numeric' ] = "numeric" ;
> else if (( $c >= «a» ) && ( $c <= "z" )) $has [ 'alpha' ] = "alpha" ;
$has [ ‘alphalower’ ] = ‘alphalower’ ;
> else if (( $c >= «A» ) && ( $c <= "Z" )) $has [ 'alpha' ] = "alpha" ;
$has [ ‘alphaupper’ ] = «alphaupper» ;
> else if (( $c == «$» ) || ( $c == «£» )) $has [ ‘currency’ ] = «currency» ;
> else if (( $c == «.» ) && ( $has [ ‘decimal’ ])) $has [ ‘decimals’ ] = «decimals» ;
> else if ( $c == «.» ) $has [ ‘decimal’ ] = «decimal» ;
> else if ( $c == «,» ) $has [ ‘comma’ ] = «comma» ;
> else if ( $c == «-» ) $has [ ‘dash’ ] = «dash» ;
> else if ( $c == » » ) $has [ ‘space’ ] = «space» ;
> else if ( $c == «/» ) $has [ ‘slash’ ] = «slash» ;
> else if ( $c == «:» ) $has [ ‘colon’ ] = «colon» ;
> else if (( $c >= » » ) && ( $c <= "~" )) $has [ 'ascii' ] = "ascii" ;
> else $has [ ‘binary’ ] = «binary» ;
>
>
mb_internal_encoding ( $current_encoding );
$string = «1234asdfA£^_<>|>~žščř» ;
echo print_r ( get_character_classes ( $string ), true );
?>
Array
(
[numeric] => numeric
[alpha] => alpha
[alphalower] => alphalower
[alphaupper] => alphaupper
[currency] => currency
[ascii] => ascii
[binary] => binary
)
Php строку utf символы
Since 5.1.0, three additional escape sequences to match generic character types are available when UTF-8 mode is selected. They are:
\p a character with the xx property \P a character without the xx property \X an extended Unicode sequence
The property names represented by xx above are limited to the Unicode general category properties. Each character has exactly one such property, specified by a two-letter abbreviation. For compatibility with Perl, negation can be specified by including a circumflex between the opening brace and the property name. For example, \p is the same as \P .
If only one letter is specified with \p or \P , it includes all the properties that start with that letter. In this case, in the absence of negation, the curly brackets in the escape sequence are optional; these two examples have the same effect:
Property | Matches | Notes |
---|---|---|
C | Other | |
Cc | Control | |
Cf | Format | |
Cn | Unassigned | |
Co | Private use | |
Cs | Surrogate | |
L | Letter | Includes the following properties: Ll , Lm , Lo , Lt and Lu . |
Ll | Lower case letter | |
Lm | Modifier letter | |
Lo | Other letter | |
Lt | Title case letter | |
Lu | Upper case letter | |
M | Mark | |
Mc | Spacing mark | |
Me | Enclosing mark | |
Mn | Non-spacing mark | |
N | Number | |
Nd | Decimal number | |
Nl | Letter number | |
No | Other number | |
P | Punctuation | |
Pc | Connector punctuation | |
Pd | Dash punctuation | |
Pe | Close punctuation | |
Pf | Final punctuation | |
Pi | Initial punctuation | |
Po | Other punctuation | |
Ps | Open punctuation | |
S | Symbol | |
Sc | Currency symbol | |
Sk | Modifier symbol | |
Sm | Mathematical symbol | |
So | Other symbol | |
Z | Separator | |
Zl | Line separator | |
Zp | Paragraph separator | |
Zs | Space separator |
Extended properties such as InMusicalSymbols are not supported by PCRE.
Specifying case-insensitive (caseless) matching does not affect these escape sequences. For example, \p always matches only upper case letters.
Sets of Unicode characters are defined as belonging to certain scripts. A character from one of these sets can be matched using a script name. For example:
Those that are not part of an identified script are lumped together as Common . The current list of scripts is:
Arabic | Armenian | Avestan | Balinese | Bamum |
Batak | Bengali | Bopomofo | Brahmi | Braille |
Buginese | Buhid | Canadian_Aboriginal | Carian | Chakma |
Cham | Cherokee | Common | Coptic | Cuneiform |
Cypriot | Cyrillic | Deseret | Devanagari | Egyptian_Hieroglyphs |
Ethiopic | Georgian | Glagolitic | Gothic | Greek |
Gujarati | Gurmukhi | Han | Hangul | Hanunoo |
Hebrew | Hiragana | Imperial_Aramaic | Inherited | Inscriptional_Pahlavi |
Inscriptional_Parthian | Javanese | Kaithi | Kannada | Katakana |
Kayah_Li | Kharoshthi | Khmer | Lao | Latin |
Lepcha | Limbu | Linear_B | Lisu | Lycian |
Lydian | Malayalam | Mandaic | Meetei_Mayek | Meroitic_Cursive |
Meroitic_Hieroglyphs | Miao | Mongolian | Myanmar | New_Tai_Lue |
Nko | Ogham | Old_Italic | Old_Persian | Old_South_Arabian |
Old_Turkic | Ol_Chiki | Oriya | Osmanya | Phags_Pa |
Phoenician | Rejang | Runic | Samaritan | Saurashtra |
Sharada | Shavian | Sinhala | Sora_Sompeng | Sundanese |
Syloti_Nagri | Syriac | Tagalog | Tagbanwa | Tai_Le |
Tai_Tham | Tai_Viet | Takri | Tamil | Telugu |
Thaana | Thai | Tibetan | Tifinagh | Ugaritic |
Vai | Yi |
The \X escape matches a Unicode extended grapheme cluster. An extended grapheme cluster is one or more Unicode characters that combine to form a single glyph. In effect, this can be thought of as the Unicode equivalent of . as it will match one composed character, regardless of how many individual characters are actually used to render it.
In versions of PCRE older than 8.32 (which corresponds to PHP versions before 5.4.14 when using the bundled PCRE library), \X is equivalent to (?>\PM\pM*) . That is, it matches a character without the «mark» property, followed by zero or more characters with the «mark» property, and treats the sequence as an atomic group (see below). Characters with the «mark» property are typically accents that affect the preceding character.
Matching characters by Unicode property is not fast, because PCRE has to search a structure that contains data for over fifteen thousand characters. That is why the traditional escape sequences such as \d and \w do not use Unicode properties in PCRE.