fed*_*o-t 34 php regex unicode multibyte mbstring
显然没有mb_trim在mb_*家庭,所以我想实现一个我自己.
我最近在php.net的评论中发现了这个正则表达式:
/(^\s+)|(\s+$)/u
Run Code Online (Sandbox Code Playgroud)
所以,我将通过以下方式实现它:
function multibyte_trim($str)
{
if (!function_exists("mb_trim") || !extension_loaded("mbstring")) {
return preg_replace("/(^\s+)|(\s+$)/u", "", $str);
} else {
return mb_trim($str);
}
}
Run Code Online (Sandbox Code Playgroud)
正则表达式似乎对我来说是正确的,但我是正则表达式的极力菜鸟.这会有效地删除字符串开头/结尾的任何 Unicode空间吗?
dec*_*eze 45
标准trim功能修剪了一些空间和类似空间的角色.这些被定义为ASCII字符,这意味着某些特定字节从0到0100 0000.
正确的 UTF-8输入永远不会包含由字节组成的多字节字符0xxx xxxx.正确的 UTF-8多字节字符中的所有字节都以1xxx xxxx.
这意味着在正确的 UTF-8序列中,字节0xxx xxxx只能引用单字节字符.trim因此,假设您有一个正确的 UTF-8序列,PHP的函数将永远不会删除"半个字符" .(非常小心不正确的 UTF-8序列.)
在\s 对ASCII正则表达式将大致相同的字符相匹配的trim.
preg具有/u修饰符的函数仅适用于UTF-8编码的正则表达式,并且/\s/u还匹配UTF8的nbsp.具有不间断空格的这种行为是使用它的唯一优势.
如果要替换其他非ASCII兼容编码中的空格字符,则这两种方法都不起作用.
换句话说,如果你试图修剪常用空格和ASCII兼容的字符串,只需使用trim.使用时请/\s/u注意文本的含义.
照顾自己:
$s1 = html_entity_decode(" Hello   "); // the NBSP
$s2 = " exotic test ? ";
echo "\nCORRECT trim: [". trim($s1) ."], [". trim($s2) ."]";
echo "\nSAME: [". trim($s1) ."] == [". preg_replace('/^\s+|\s+$/','',$s1) ."]";
echo "\nBUT: [". trim($s1) ."] != [". preg_replace('/^\s+|\s+$/u','',$s1) ."]";
echo "\n!INCORRECT trim: [". trim($s2,' ') ."]"; // DANGER! not UTF8 safe!
echo "\nSAFE ONLY WITH preg: [".
preg_replace('/^[\s]+|[\s]+$/u', '', $s2) ."]";
Run Code Online (Sandbox Code Playgroud)
kba*_*kba 20
我不知道你正在尝试用你定义的无限递归函数做什么,但如果你只想要一个多字节安全的修剪,这将有效.
function mb_trim($str) {
return preg_replace("/(^\s+)|(\s+$)/us", "", $str);
}
Run Code Online (Sandbox Code Playgroud)
此版本支持第二个可选参数$ charlist:
function mb_trim ($string, $charlist = null)
{
if (is_null($charlist)) {
return trim ($string);
}
$charlist = str_replace ('/', '\/', preg_quote ($charlist));
return preg_replace ("/(^[$charlist]+)|([$charlist]+$)/us", '', $string);
}
Run Code Online (Sandbox Code Playgroud)
但是不支持范围"..".
好的,所以我采用了@ edson-medina的解决方案并修复了一个错误并添加了一些单元测试.这是我们用来为mb对应物赋予trim,rtrim和ltrim的3个函数.
////////////////////////////////////////////////////////////////////////////////////
//Add some multibyte core functions not in PHP
////////////////////////////////////////////////////////////////////////////////////
function mb_trim($string, $charlist = null) {
if (is_null($charlist)) {
return trim($string);
} else {
$charlist = preg_quote($charlist, '/');
return preg_replace("/(^[$charlist]+)|([$charlist]+$)/us", '', $string);
}
}
function mb_rtrim($string, $charlist = null) {
if (is_null($charlist)) {
return rtrim($string);
} else {
$charlist = preg_quote($charlist, '/');
return preg_replace("/([$charlist]+$)/us", '', $string);
}
}
function mb_ltrim($string, $charlist = null) {
if (is_null($charlist)) {
return ltrim($string);
} else {
$charlist = preg_quote($charlist, '/');
return preg_replace("/(^[$charlist]+)/us", '', $string);
}
}
////////////////////////////////////////////////////////////////////////////////////
Run Code Online (Sandbox Code Playgroud)
这是我为感兴趣的人写的单元测试:
public function test_trim() {
$this->assertEquals(trim(' foo '), mb_trim(' foo '));
$this->assertEquals(trim(' foo ', ' o'), mb_trim(' foo ', ' o'));
$this->assertEquals('foo', mb_trim(' Åfoo? ', ' Å?'));
}
public function test_rtrim() {
$this->assertEquals(rtrim(' foo '), mb_rtrim(' foo '));
$this->assertEquals(rtrim(' foo ', ' o'), mb_rtrim(' foo ', ' o'));
$this->assertEquals('foo', mb_rtrim('foo? ', ' ?'));
}
public function test_ltrim() {
$this->assertEquals(ltrim(' foo '), mb_ltrim(' foo '));
$this->assertEquals(ltrim(' foo ', ' o'), mb_ltrim(' foo ', ' o'));
$this->assertEquals('foo', mb_ltrim(' Åfoo', ' Å'));
}
Run Code Online (Sandbox Code Playgroud)
您还可以修剪 UTF-8 字符串上的非 ascii 兼容空格(例如不间断空格),即使使用修饰符preg_replace('/^\p{Z}+|\p{Z}+$/u','',$str);
\s也只会匹配“ascii 兼容”空格字符。
但会匹配所有已知的 unicode 空格字符u\p{Z}