如何检查Unicode格式良好?



就像我们中的许多人一样,我接受Unicode用户名作为服务,就像我们中的许多人一样,我有时会让那些试图使用Unicode复杂性的人做一些有趣的事情。使用Unicode可以做的一件有趣的事情是,用一个组合字符开始一个字符串,然后在与其他字符串(日志消息、用户可见消息、HTML片段、配置文件页面、&c&c&c)连接时,与它前面的字符串(通常但不一定是空格)组合。虽然这很少会引起严重的问题,但它可能会让人感到奇怪和困惑,虽然我讨厌成为派对的扫兴者,但我觉得有时候对任何人来说都有点太有趣了。

在我的特殊情况下,我当然可以专门检查输入开始时的字符组合,但是考虑到前面提到的Unicode的复杂性,我不怀疑还有无数其他有趣的事情可以用它来完成,我确信有明确定义的规则可以将Unicode视为格式良好,但我不能说我能够轻松找到任何规则。总的来说,把Zalgo驱逐出去是件好事。

所以这就是我的问题:在这种情况下如何检查Unicode字符串是否格式良好?

Zalgo是格式良好的Unicode。这是奇怪的Unicode,但完全合法。以组合字符开头的字符串也是完全合法的。参见在Unicode中可以单独使用组合字符吗?在之前的讨论中。引用的文本仍然存在于规范的第14版(第2.11节):

所有组合字符都可以应用于任何基本字符,并且原则上可以用于任何脚本。与其他字符一样,将组合字符分配到一个块或另一个块只标识其主要用途;它不打算定义或限制它可以应用的字符范围。在Unicode标准中,所有的字符代码序列都是允许的。(原文重音)

有一个流安全文本格式,它解决了你所描述的一些问题,因为它将组合字符的数量限制在30,但我怀疑这并没有解决你真正关心的问题,那就是你不想看到不像"真实语言"的东西。

在某种程度上,这是不存在的。人类语言是如此的狂野和多变,以至于Unicode仍然没有捕捉到所有的语言。试图限制可以表达的内容与Unicode努力做到的相反。所以无论你设计什么,都必须是特别的。

对于避免将动态文本与之前的静态文本(例如,在日志消息中)组合的特定问题,Unicode完全支持。你想要的代码点是U+200C ZERO WIDTH NON-JOINER。它的意思是"即使围绕这个代码点的两个代码点通常会连接在一起,也不要。"因此,您可以将其添加到日志消息模板中,以确保消息不会以这种方式损坏。不需要编写特殊规则来修改或检查字符串。零宽度标记是Unicode打算解决这些问题的方式。(参见U+200E LEFT-TO-RIGHT MARK和它的朋友,当嵌入RTL语言时,你可能会发现它对防止日志消息有奇怪的布局很有用。)

但是没有标准的方法来排除Zalgo。Zalgo是人类表达,Unicode明确允许它。但我也会把说明书的下一段留给你:

这并不意味着实现必须同样地支持所有可能的组合。

您可以随意使用Unicode工具修改字符串。

最新更新