如何检测或正确识别奇怪字符的长度?

时间:2011-12-23 07:32:50

标签: php regex unicode utf-8

我正在以编程方式将长连字符插入长字,并且遇到有异常字符的问题,特别是:■

任何超过10个字符的单词都会获得软连字符处理。单词用正则表达式定义:[A-Za-z0-9,.]+(包括长数字)。如果我将包含上述两个unicode字符的字符串与该正则表达式分开,我得到一个像这样的“字”:■■

我的脚本然后遍历每个单词,测量长度(mb_strlen($word, 'UTF-8')),如果它超过任意数量的字符,循环遍历字母并在整个地方插入软连字符(每三个字符,不是最后五个字符。)

使用■■,字长足以触发替换(10)。因此插入了软连字符,但它们将插入字符中。所以我得出的是:

�­�■

在数据库中,这些■字符被存储(在json_encoded块中)为“\ u2002”,因此我可以看到字符串长度的来源。我需要的是一种识别这些字符的方法,因此我可以避免在包含它们的单词中添加软连字符。任何想法,任何人?

(或者,或者测量字符串长度的方法,将它们计算为单个字符,然后将该字符串拆分为字符而不将其分割为多字节字符。)

1 个答案:

答案 0 :(得分:1)

与关于猜测的评论中列出的注意事项相同,但没有看到代码:

  

mb_strlen($word, 'UTF-8'),如果超过任意数量的字符,则循环显示字母

我怀疑你实际上正在循环遍历字节。如果对字符串使用数组访问表示法,则会发生这种情况。

当您使用UTF-8等多字节编码时,字母(或更常见的“字符”)可能会占用多个字节的存储空间。如果在字节序列的中间插入或删除,则会得到错误的结果。

这就是为什么你必须使用mb_strlen而不是普通的strlen。某些语言具有本机Unicode字符串类型,其中每个项目都是一个字符,但PHP字符串完全基于字节,如果您希望以逐个字符的方式与它们进行交互,则必须使用mb_string functions。特别是要从您使用mb_substr的字符串中读取单个字符,并将索引从0循环到mb_strlen

获取匹配的单词并使用正则表达式替换在每个序列之间插入软连字符可能更简单。您可以使用u标志为正则表达式提供多字节字符串支持。 (这仅适用于UTF-8,但UTF-8是您实际想要使用的唯一多字节编码。)

const SHY= "\xC2\cAD"; // U+00AD Soft Hyphen encoded as UTF-8
$wrappableword= preg_replace('/.{3}\B/u', '$1'.SHY, $longword);