PHP 替换字符串中的字符代码 8217 时出现意外输出
PHP unexpected output when replacing character code 8217 in string
我 运行 遇到了意外的字符替换问题。字符编码为8217,’
.
我试过用斜杠转义字符,但没有什么区别。
php > $a = preg_replace('/([.,\'"’:?!])<\/a>/', '</a>', 'letter">Evolution’</a> </li>');
php > echo($a);
// => letter">Evolution/a> </li>
// Just to show that it works if the character is different
php > $a = preg_replace('/([.,\'"’:?!])<\/a>/', '</a>', 'letter">Evolution"</a> </li>');
php > echo($a);
letter">Evolution</a>" </li>
我希望它能输出
letter">Evolution</a>’ </li>
而不是
letter">Evolution/a> </li>
默认情况下,pcre(php 正则表达式引擎)将您的模式视为一连串的单字节编码字符。因此,当您编写 [’]
时,您将获得一个字符 class,其中三个字节对正确的单引号 (U+2019) 进行了编码,即:\xE2
、\x80
, \x99
.
换句话说,在此默认模式下写入 "/[’]/"
就像写入 "/[\xE2\x80\x99]/"
或 "/[\x80\xE2\x99]/"
或 "/[\x99\xE2\x80]/"
等,正则表达式引擎看不到表示字符 ’
但只有三个字节的字节序列。
这就是你得到奇怪结果的原因,因为 [.,\'"’:?!]
只会匹配 ’
的最后一个字节,所以 \x99
.
要解决此问题,您必须强制正则表达式引擎将您的模式读取为 UTF-8 编码字符串。您可以通过以下方式之一完成此操作:
preg_replace('~(*UTF)([.,\'"’:?!])</a>~', '</a>', 'letter">Evolution’</a> </li>');
preg_replace('~([.,\'"’:?!])</a>~u', '</a>', 'letter">Evolution’</a> </li>');
这次三个字节 \xE2\x80\x99
被视为字符 ’
.
的原子序列
注意:(*UTF)
仅用于读取模式,但 u
修饰符做更多的事情:它扩展了 shorthand 个字符 classes(如 \s
, \w
,\d
) 到 unicode 字符并检查主题字符串是否为 utf-8 编码。
只需在正则表达式中添加 unicode 标志:
$a = preg_replace('/([.,\'"’:?!])<\/a>/u', '</a>', 'letter">Evolution’</a> </li>');
# here ___^
echo($a);
我 运行 遇到了意外的字符替换问题。字符编码为8217,’
.
我试过用斜杠转义字符,但没有什么区别。
php > $a = preg_replace('/([.,\'"’:?!])<\/a>/', '</a>', 'letter">Evolution’</a> </li>');
php > echo($a);
// => letter">Evolution/a> </li>
// Just to show that it works if the character is different
php > $a = preg_replace('/([.,\'"’:?!])<\/a>/', '</a>', 'letter">Evolution"</a> </li>');
php > echo($a);
letter">Evolution</a>" </li>
我希望它能输出
letter">Evolution</a>’ </li>
而不是
letter">Evolution/a> </li>
默认情况下,pcre(php 正则表达式引擎)将您的模式视为一连串的单字节编码字符。因此,当您编写 [’]
时,您将获得一个字符 class,其中三个字节对正确的单引号 (U+2019) 进行了编码,即:\xE2
、\x80
, \x99
.
换句话说,在此默认模式下写入 "/[’]/"
就像写入 "/[\xE2\x80\x99]/"
或 "/[\x80\xE2\x99]/"
或 "/[\x99\xE2\x80]/"
等,正则表达式引擎看不到表示字符 ’
但只有三个字节的字节序列。
这就是你得到奇怪结果的原因,因为 [.,\'"’:?!]
只会匹配 ’
的最后一个字节,所以 \x99
.
要解决此问题,您必须强制正则表达式引擎将您的模式读取为 UTF-8 编码字符串。您可以通过以下方式之一完成此操作:
preg_replace('~(*UTF)([.,\'"’:?!])</a>~', '</a>', 'letter">Evolution’</a> </li>');
preg_replace('~([.,\'"’:?!])</a>~u', '</a>', 'letter">Evolution’</a> </li>');
这次三个字节 \xE2\x80\x99
被视为字符 ’
.
注意:(*UTF)
仅用于读取模式,但 u
修饰符做更多的事情:它扩展了 shorthand 个字符 classes(如 \s
, \w
,\d
) 到 unicode 字符并检查主题字符串是否为 utf-8 编码。
只需在正则表达式中添加 unicode 标志:
$a = preg_replace('/([.,\'"’:?!])<\/a>/u', '</a>', 'letter">Evolution’</a> </li>');
# here ___^
echo($a);