unicode 异常字符列表
The list of unicode unusual characters
从哪里可以获得所有不表现为简单字符的 unicode 字符的完整列表。示例:字符 0x0363(之前没有另一个字符不会打印),字符 0x0084(打印时会做奇怪的事情)。我只需要这些不寻常字符的原始列表,用无害的东西替换它们,以避免不必要的输出效果。常规字符(不在此列表中的字符)在打印时应仅使用一个字符位置(= 光标向右移动 +1),不应依赖于前一个或下一个字符,并且不应以任何方式影响打印样式。
因评论多而编辑:
我有一些 unicode 字符串,通常由“普通”字符组成,例如 0x20-0x7E 或西里尔字母。此外,还有许多其他常见的 unicode 字符,可以安全地假设它们具有 strlen() = 1。该字符串打印在终端上,我应该知道光标的结果位置。我不想使用一些复杂且不稳定的库来执行此操作,我希望使用最简单的逻辑来执行此操作。每个有问题的字符都可以替换为 U+0xFFFD 或类似“”的内容(ASCII 字符串及其索引而不是字符本身)。我想要一个“可能有问题”的字符列表来替换。在这个列表中也可以有一些没有问题的字符,但不要太多。
对此没有简单的算法。您可能需要一个复杂但极其稳定的库:libicu,或基于它的东西。基本上所有其他从事此类工作的库都基于 libicu,它由 Unicode 组织维护。
如果你不想使用官方库(或基于他们库的东西),你需要解析 Unicode Character Database yourself. In particular, you need to look at Character Properties, and parse the files in the UCD.
我相信你要求 Bidi_Class (i.e. "direction") to be Left_To_Right, Canonical_Combining_Class to be Not_Reordered, and Joining_Type 成为 Non_Joining。
您可能还想检查 General_Category 并避免 M*(标记)和 C*(其他)。
这应该适用于某些表情符号,但整个方法会破坏很多看起来简单但实际上并不简单的表情符号。最著名的是:❤️,这是两个“字符”,而不是一个。您可能想要过滤掉 Emoji。作为一个简单的起点,您可能希望将自己限制在基本多语言平面 (BMP),即代码点 0000-FFFF。几乎根据定义,超出此范围的任何东西都是罕见或不寻常的。 BMP 确实包含一些表情符号,但大多数表情符号(和所有新的表情符号)都在范围之外。
请记住,即使是名义上固定宽度的字体,单个字符的字形仍然可以具有完全不同的宽度。例如, (U+12219 CUNEIFORM SIGN LUGAL OPPOSING LUGAL) 是您描述的完全“正常”字符。它是从左到右的。它不依赖于或影响它周围的字符(它是非组合和非连接的)。它的“字符长度”是 1。它的字形在大多数字体中也非常宽并且破坏了很多布局。我不知道 Unicode 数据库中有什么会警告你这一点,因为“字形宽度”完全是字体的函数,而不是字符,而且 Unicode 明确地不考虑字体。 (也就是说,大多数最有问题的字符都在 BMP 之外。可能最常见的例外是 DŽ,但是许多固定宽度的字体都有一个窄字形:DŽ
。)
Let's write some cuneiform in a fixed-width font.
Normally, every character should line up with a character above.
Here: . See how these characters don't align correctly?
Not only is it a very wide glyph, but its width is not even a multiple.
At least not in my font (Mac Safari 15.0).
But DŽ is ok.
还要记住,有多种方法可以对同一个“字符”进行编码。例如,é 可以是一个“简单”字符 (U+00E9),也可以是两个字符 (U+0065, U+0301)。所以在某些情况下 é 可能会在您的方案中打印,而在其他情况下则不会。我怀疑这可以解决您的问题,但如果不是,您将需要应用 normalization form(可能是 NFC)。
从哪里可以获得所有不表现为简单字符的 unicode 字符的完整列表。示例:字符 0x0363(之前没有另一个字符不会打印),字符 0x0084(打印时会做奇怪的事情)。我只需要这些不寻常字符的原始列表,用无害的东西替换它们,以避免不必要的输出效果。常规字符(不在此列表中的字符)在打印时应仅使用一个字符位置(= 光标向右移动 +1),不应依赖于前一个或下一个字符,并且不应以任何方式影响打印样式。
因评论多而编辑: 我有一些 unicode 字符串,通常由“普通”字符组成,例如 0x20-0x7E 或西里尔字母。此外,还有许多其他常见的 unicode 字符,可以安全地假设它们具有 strlen() = 1。该字符串打印在终端上,我应该知道光标的结果位置。我不想使用一些复杂且不稳定的库来执行此操作,我希望使用最简单的逻辑来执行此操作。每个有问题的字符都可以替换为 U+0xFFFD 或类似“”的内容(ASCII 字符串及其索引而不是字符本身)。我想要一个“可能有问题”的字符列表来替换。在这个列表中也可以有一些没有问题的字符,但不要太多。
对此没有简单的算法。您可能需要一个复杂但极其稳定的库:libicu,或基于它的东西。基本上所有其他从事此类工作的库都基于 libicu,它由 Unicode 组织维护。
如果你不想使用官方库(或基于他们库的东西),你需要解析 Unicode Character Database yourself. In particular, you need to look at Character Properties, and parse the files in the UCD.
我相信你要求 Bidi_Class (i.e. "direction") to be Left_To_Right, Canonical_Combining_Class to be Not_Reordered, and Joining_Type 成为 Non_Joining。
您可能还想检查 General_Category 并避免 M*(标记)和 C*(其他)。
这应该适用于某些表情符号,但整个方法会破坏很多看起来简单但实际上并不简单的表情符号。最著名的是:❤️,这是两个“字符”,而不是一个。您可能想要过滤掉 Emoji。作为一个简单的起点,您可能希望将自己限制在基本多语言平面 (BMP),即代码点 0000-FFFF。几乎根据定义,超出此范围的任何东西都是罕见或不寻常的。 BMP 确实包含一些表情符号,但大多数表情符号(和所有新的表情符号)都在范围之外。
请记住,即使是名义上固定宽度的字体,单个字符的字形仍然可以具有完全不同的宽度。例如, (U+12219 CUNEIFORM SIGN LUGAL OPPOSING LUGAL) 是您描述的完全“正常”字符。它是从左到右的。它不依赖于或影响它周围的字符(它是非组合和非连接的)。它的“字符长度”是 1。它的字形在大多数字体中也非常宽并且破坏了很多布局。我不知道 Unicode 数据库中有什么会警告你这一点,因为“字形宽度”完全是字体的函数,而不是字符,而且 Unicode 明确地不考虑字体。 (也就是说,大多数最有问题的字符都在 BMP 之外。可能最常见的例外是 DŽ,但是许多固定宽度的字体都有一个窄字形:DŽ
。)
Let's write some cuneiform in a fixed-width font.
Normally, every character should line up with a character above.
Here: . See how these characters don't align correctly?
Not only is it a very wide glyph, but its width is not even a multiple.
At least not in my font (Mac Safari 15.0).
But DŽ is ok.
还要记住,有多种方法可以对同一个“字符”进行编码。例如,é 可以是一个“简单”字符 (U+00E9),也可以是两个字符 (U+0065, U+0301)。所以在某些情况下 é 可能会在您的方案中打印,而在其他情况下则不会。我怀疑这可以解决您的问题,但如果不是,您将需要应用 normalization form(可能是 NFC)。