可靠地旋转任何字符串

时间:2016-02-04 10:04:41

标签: php unicode multibyte multibyte-functions

我正在尝试使用多字节字符串以及如何处理它们。使用您可以在此处看到的代码

https://gist.github.com/charlydagos/89f67808e01f97e6de91

我成功地旋转了大多数琴弦。但是我注意到了这行

$chr = mb_substr($str, $i, 1);

不适用于flag emojis,因为它们使用多个unicode代码点。

您可以在自己的shell中尝试以下操作:

这会产生所需的输出:$ php string_rotate_mb.php "你好"

然而$ php string_rotate_mb.php ""会返回[H][C]

这在技术上是正确的,它确实旋转了字符串。但实际上它的单个字形和我想要的输出是单独的标志(或一系列标志,然后变成更加乱码的字形,有时甚至将它变成不同的标志)。

然后,如何可靠地确定我应该使用$length = 1抓取$length = 2$length = N(或mb_substr)子字符串?

供参考,我使用PHP 7.0.2 (cli) (built: Jan 7 2016 10:40:26) ( NTS )ZSH_VERSION = 5.2LC_ALL=en_us.utf-8iTerm2: Build 2.9.git.8dff8db518

更新 - 2016年2月5日

解决方案:https://gist.github.com/charlydagos/6755ad994da07a7b4959#file-string_rotate_working-php-L39-L56

感谢roeland介绍Grapheme Clusters的概念。以下链接中也有好消息

1 个答案:

答案 0 :(得分:1)

还有很多例子失败了:

  • 撰写角色:比较êê(第一个实际上是U + 0302和U + 0065)

  • 变体:例如。表情符号可以有黑色/白色或颜色变体︎对️。这是通过在表情符号之后添加变体选择器来完成的。种族差异的类似问题:。 (注意:对此的支持有点不稳定,但至少Windows 10支持这些变体)

  • 标志,由两个代码点组成。

  • 使用分数短划线(U + 2044)的分数也可以使用一个字形进行渲染。例如。的 1/2 即可。请注意 1/2

  • 的差异

等等......

我认为你所寻找的是石墨聚类。没有图书馆支持,我认为这很难做到。

对于最近的PHP版本,有intl扩展名。您可以使用the grapheme functions循环遍历群集。