PHP的str_replace()
仅用于ANSI字符串,因此可以破坏UTF-8字符串。但是,如果只有有效的UTF-8字符串作为参数,那么它是二进制安全的吗?
编辑:我不是在寻找替代函数,我只想知道这个假设是否正确。
答案 0 :(得分:19)
是。 UTF-8经过精心设计,允许进行此类和其他类似的非Unicode感知处理。
在UTF-8中,表示有效字符的任何非ASCII字节序列始终以\xC0-\xFF
范围内的字节开头。此字节可能不会出现在序列中的任何其他位置,因此您无法生成与字符的一部分匹配的有效UTF-8序列。
对于较旧的多字节编码不是这种情况,其中字节序列的不同部分是无法区分的。这导致了很多问题,例如尝试替换Shift-JIS字符串中的ASCII反斜杠(其中字节\x5C
可能是表示其他内容的字符序列的第二个字节)。
答案 1 :(得分:5)
这是正确的,因为UTF-8多字节字符是非ASCII(128+字节值)字符,以一个字节开头,该字节定义了后面的字节数,因此您不会意外地最终匹配一个UTF-8的一部分多字节角色与另一个角色。
可视化(抽象地):
a
表示ASCII字符2x
表示2字节字符3xx
表示3字节字符4xxx
表示4字节字符如果你匹配,比如a2x3xx
(ASCII范围内的a
个字节),那么a
< x
和2x
不能是3xx
或4xxx
的子集,等等,您可以安全地确保您的UTF-8正确匹配,前提条件是所有字符串绝对是有效的UTF-8。
编辑:有关不太抽象的解释,请参阅bobince的答案。
答案 2 :(得分:1)
好吧,我做有一个反例:我有一个UTF8编码的设置“.ini”文件,指定了电子邮件发件人姓名之类的应用设置。它说的是:
email_from = Märta
我从那里读到变量$sender
。现在我替换了消息体(再次使用UTF8)
问候 {发件人}
$message = str_replace("{sender}",$sender_name,$message);
电子邮件在各个方面都是绝对正确的,但发件人完全被打破了。当UTF字符串出现问题时,还有其他情况(如explode())。它在转换之前是健康的,但不是之后。很抱歉,似乎没有办法纠正这种行为。
编辑:实际上,explode()
涉及解析.ini文件,因此问题很可能在于这个功能,因此str_replace()
可能是无辜的。< / p>
答案 3 :(得分:0)
是的,我认为这是正确的,至少我找不到任何反例。
答案 4 :(得分:0)
不,你不能。
从实践中我告诉你,如果你有一些多字节符号,如◊等,其他非多字节,它不能正常工作,因为有符号需要2-4来放置它们,
str_replace
获取固定的字节,并替换...结果我们有一些东西不是任何符号垃圾等。