php去掉多字节_PHP的多字节处理拾遗

在处理已一个PHPwind对于敏感词识别错误的问题中,发现了phpWind对于多字节处理存在很大的问题,例如admin\cache.php中如下代码:

$query = $db->query("SELECT * FROM pw_wordfb WHERE classid NOT IN ($classid) ORDER BY id");

while (@extract($db->fetch_array($query))) {

if ($word) {

$word = trim(preg_quote($word,'/'));

//$word = preg_replace("/\\\{(\d+)\\\}/", ".{0,\\1}", $word);

switch ($type) {

case 1:

$wordsfb[$word] = $wordreplace;

break;

case 2:

$alarm[$word] = $wordreplace;

break;

case 3:

$replace[$word] = $wordreplace;

break;

default:

$replace[$word] = $wordreplace;

break;

}

}

}

这里对于关键词作了$word = trim(preg_quote($word,'/'));处理,这条语句咋一眼看上去没有什么问题,但是别忘了,preg_quote是为单字节而设计的函数,因此当用他处理多字节串字符串的时候就有可能出错,为什么说有可能呢?那是因为这跟编码有关系,例如,在GBK编码下执行:

echo preg_quote('遊行');

他会莫名奇妙的输出運[行,这其实一点也不奇怪,这是因为遊行对应的字节码为DF 5B D0 D0,这其中5B对应相对于ASCII中的编码即为[,也就是说 preg_quote函数把DF 5B(遊)这个整体拆分开来处理了,把遊的第二个编码当成了单个的ascii码[处理,给他也加上了\反斜杠进行转义,于是原先的编码就变成了DF 5C 5B D0 D0,即運[行。

其实仔细考虑下,多字节编码的问题其实是普遍存在的,例如我们常用的str_replace函数,还有spilt函数,这些常用函数其实都是存在多字节处理出错风险的。只是因为大部分情况下不大容易出错,因此我们就忽略这些风险。当然对于多字节的字符串的处理PHP官方库中还是有相对应的mb_api进行处理的,PHP多字节处理函数,但是发现这其中居然没有mb_str_replace()这个函数,这是我最急需的一个函数,在该页的comments中发现了一个宝贝。

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($subject, 0, $pos) . $r . mb_substr($subject, $pos + mb_strlen($s));

$pos = mb_strpos($subject, $s, $pos + mb_strlen($r));

}

}

return $subject;

}

该函数能比较完美的处理多字节的字符串替换需求。基于此也诞生了多字符串正则转义函数。

function mb_preg_quote($subject){

$search = array('.','\\','+','*','?','[','^',']','$','(',')','{','}','=','!','','|',':','-');

$replace = array('\.','\\\\','\+','\*','\?','\[','\^','\]','\$','\(','\)','\{','\}','\=','\!','\','\|','\:','\-');

return mb_str_replace($search,$replace,$subject);

}

当然,要想多字节字符串处理函数有效,需要确保两点

安装了mb扩展

mb_internal_encoding()函数 — 设置/获取内部字符编码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值