PHP替换字符编码8217时出现意外输出问题求助
解决Unicode右单引号(U+8217)的正则替换问题
最近碰到个头疼的字符替换问题——就是那个Unicode编码为U+8217的右单引号(’),我想用正则把它从</a>标签前面移到后面,结果用反斜杠转义根本不管用,直接把</a>给搞坏了!
先看我出问题的代码:
php > $a = preg_replace('/([.,\'"’:?!])<\/a>/', '</a>\1', 'letter">Evolution’</a> </li>'); php > echo($a); // => letter">Evolution/a> </li>
对比用普通双引号的正常情况:
// 对比不同字符时的正常情况 php > $a = preg_replace('/([.,\'"’:?!])<\/a>/', '</a>\1', 'letter">Evolution"</a> </li>'); php > echo($a); // => letter">Evolution</a>" </li>
我本来想要的结果是letter">Evolution</a>’ </li>,结果出来个letter">Evolution/a> </li>,这就离谱!
问题根源 & 解决方案
问题出在正则表达式的编码匹配逻辑上!那个U+8217是多字节的Unicode字符,而默认的PCRE正则在PHP里是按单字节处理的,它没法正确识别这个多字节引号,匹配时把</a>的部分字节给误判了,才导致标签被破坏。
解决办法很简单,给正则加上u修饰符(开启Unicode模式),同时把这个特殊引号纳入匹配范围:
方案1:用Unicode转义字符
把正则里的匹配组加上\x{2019}(U+8217的Unicode转义写法),再加上u修饰符:
php > $a = preg_replace('/([.,\'"’:?!\x{2019}])<\/a>/u', '</a>\1', 'letter">Evolution’</a> </li>'); php > echo($a); // => letter">Evolution</a>’ </li>
方案2:直接写入特殊引号字符
如果你的代码文件本身是UTF-8编码,直接把’放进正则的匹配组里,再加上u修饰符也能正常工作:
php > $a = preg_replace('/([.,\'"’:?!’])<\/a>/u', '</a>\1', 'letter">Evolution’</a> </li>'); php > echo($a); // => letter">Evolution</a>’ </li>
加了u修饰符后,正则就会按完整的Unicode字符来处理,不会把多字节字符拆成单个字节匹配,自然就能正确识别那个特殊引号,完成我们想要的替换啦!
内容的提问来源于stack exchange,提问作者David da Silva
相关产品推荐
相关产品推荐

