【问题标题】:How can I detect, or correctly identify the length, of strange characters?如何检测或正确识别奇怪字符的长度?
【发布时间】:2011-12-23 07:32:50
【问题描述】:

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

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

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

使用■■,字长足以触发替换 (10)。所以软连字符被插入,但它们被插入字符。所以我得到的是这样的:

�­�■

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

(要么是这样,要么是测量字符串长度的方法,将它们计为单个字符,然后将字符串拆分为字符,而不是通过多字节字符中途拆分。)

【问题讨论】:

  • 所以您将处理应用于json_encoded 文本而不是“真正的”UTF-8 文本?如果是这样,为什么不首先json_decode 文本,然后应用您的处理,然后再次json_encode 处理的文本?因为mb_strlen("■■", 'UTF-8') 应该返回正确的字符长度:2
  • 据我了解,正则表达式可能存在多字节编码问题。
  • Dr.Molle:我把这个词当作一个数组,循环遍历这些字母。每三分之一,我添加一个连字符。
  • vstm:处理应用于解码的文本。但你是对的 - 我只是像你一样对内容进行了手动测试,mb_strlen 的长度是正确的。也许还有其他问题。
  • 我认为您需要发布一些代码。我看不到 \u2002 (U+2002 EN SPACE) 如何匹配正则表达式,我看不到它如何转换为 U+25A= BLACK SQUARE “■”,更不用说在字符内插入什么字符可能意味着。我也看不出在每三个字母后任意插入软连字符的意义——这在我所知道的任何语言中都是不正确的。

标签: php regex unicode utf-8


【解决方案1】:

与 cmets 中列出的关于在没有看到代码的情况下进行猜测的警告相同:

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);

【讨论】:

  • 是的,就是这样 - 我正在循环遍历字节。非常感谢!
猜你喜欢
  • 2013-07-19
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-28
  • 1970-01-01
  • 2011-03-30
  • 1970-01-01
相关资源
最近更新 更多