如何移除iconv转译ASCII字符串中的多余问号字符?
如何移除iconv TRANSLIT转译后的多余问号?
问题场景
我用iconv把UTF-8字符串转译为ASCII可打印字符,代码如下:
$str = 'Thê qúïck 😈 brõwn fõx júmps?😈 Óvér thé lázy dõg?😈'; $out = iconv('UTF-8', 'ASCII//TRANSLIT', $str); var_dump($out); // 输出结果:'The quick ? brown fox jumps?? Over the lazy dog??'
现在需要移除转译结果里的多余问号,但要保留//TRANSLIT正常转译的字符(比如áéïõú转成aeiou),不想用逐字符对比的笨方法,求更优解决思路。
解决方案
1. 先过滤不可转译字符,再执行TRANSLIT转译
提前把那些iconv会转成问号的Unicode字符过滤掉,转译后就不会产生多余问号。用正则匹配保留拉丁字符、标点和空白,删掉其他字符:
$str = 'Thê qúïck 😈 brõwn fõx júmps?😈 Óvér thé lázy dõg?😈'; // 过滤非拉丁、非标点、非空白的字符 $filtered = preg_replace('/[^\p{Latin}\p{Punct}\s]/u', '', $str); $out = iconv('UTF-8', 'ASCII//TRANSLIT', $filtered); var_dump($out); // 输出:'The quick brown fox jumps? Over the lazy dog?'
2. 精准替换转译产生的问号
如果不想提前过滤,可以在转译后,只删除那些对应原字符不是问号的转译问号。用mb_str_split正确拆分多字节原字符串,再逐对应处理:
$str = 'Thê qúïck 😈 brõwn fõx júmps?😈 Óvér thé lázy dõg?😈'; $out = iconv('UTF-8', 'ASCII//TRANSLIT', $str); $originalChars = mb_str_split($str); $translitChars = str_split($out); $final = ''; foreach ($translitChars as $index => $char) { if ($char === '?' && isset($originalChars[$index]) && $originalChars[$index] !== '?') { continue; } $final .= $char; } var_dump($final); // 输出:'The quick brown fox jumps? Over the lazy dog?'
3. 用intl扩展的Transliterator精准控制转译
如果服务器支持intl扩展,用Transliterator可以一步到位生成无多余问号的结果,转译逻辑更灵活:
$str = 'Thê qúïck 😈 brõwn fõx júmps?😈 Óvér thé lázy dõg?😈'; // 转译规则:去变音符号→转拉丁字符→转ASCII→移除非打印字符 $transliterator = Transliterator::create('NFD; [:Nonspacing Mark:] Remove; NFC; Any-Latin; Latin-ASCII; [^\p{Print}] Remove'); $out = $transliterator->transliterate($str); var_dump($out); // 输出:'The quick brown fox jumps? Over the lazy dog?'
内容的提问来源于stack exchange,提问作者Jeff
相关产品推荐
相关产品推荐

