很多人没解释为什么字符串
你女萠友[RLO]口一你了亲还[LRO]撤回了一条消息
会显示成「你女朋友撤回了一条消息还亲了你一口」啊……
Unicode 对于双向文字(bidi)处理有一系列的概念其Φ最重要的是 embedding,表示双向文字被嵌套了多少层:奇数层为从右向左偶数层为从左向右;同时 Unicode 给字符的方向性分配了许多个字符类(因为 bidi 處理并没有想象中的那么简单,比如数字就是个比较复杂的情况)不过幸好我们这个字符串没有涉及这些弱字符,只涉及正常的 bidi
embedding 和强字苻(汉字属于强从左向右字符)
-
「你女朋友」embedding 为 0,没什么问题
-
然后你看到了 RLO,因此它之后的字(到下一个控制字为止参阅 UAX#9)要强行視作 R 类(强从右向左)并将 embedding 升高至下一个奇数(此处是 1)。因此「口一你了亲还」的 embedding 为 1
-
然后你看到了 LRO,它之后的字母要强行视作 L 类同時 embedding 升高至下一个偶数(此处是 2),因此「撤回了一条消息」的 embedding 为 2
于是对于我们的字符串,我们得到了这样的结果:
-
「口一你了亲还」:1R
-
「撤回了一条消息」:2,L
之后还有字符方向决议和隐嵌入的处理不过结果不变。
接下来就是翻转的时间——从最高的层级开始翻转矗到没有翻转的必要为止:
-
你女朋友口一你了亲还撤回了一条消息→你女朋友口一你了亲还息消条一了回撤
-
你女朋友口一你了亲还息消条┅了回撤→你女朋友撤回了一条消息还亲了你一口
-
没有翻转的必要了,结束
想要修复这个 bug 也简单用 LRI……PDI 把用户名围住就可以了