Unicode 可打印字符的范围是多少?

Posted

技术标签:

【中文标题】Unicode 可打印字符的范围是多少?【英文标题】:What is the range of Unicode Printable Characters? 【发布时间】:2011-04-15 18:26:45 【问题描述】:

谁能告诉我 [例如。 Ascii 可打印字符范围为 \u0020 - \u007f]

【问题讨论】:

\u0000 - \u0020 在 Unicode 中也无法打印 更像\u0020 - \u007e 你肯定对这个问题很讨厌。我喜欢这个主意。 使用 UTF-16 代码单元的编程语言符号来给出一系列 ASCII 代码点有点奇怪(但在数字和字符方面,它确实有效)。 这个问题非常简单,但答案却不是。所以自然每个人都会声称这个问题是无效的。这是一个关于 Unicode 的问题,而不是关于字体(afaik)的问题,所以重要的是符号是否可以在概念上被绘制出来。控制字符、零宽度字符和修饰符被明确排除在此列表之外。 \u0020 和其他空格 (?) 是一种极端情况,但这并不会使问题无法回答。无论如何,我建议您访问en.wikipedia.org/wiki/List_of_Unicode_characters 以进一步调查此事。 【参考方案1】:

见,http://en.wikipedia.org/wiki/Unicode_control_characters

您可能需要特别关注 C0 和 C1 控制字符 http://en.wikipedia.org/wiki/C0_and_C1_control_codes

wiki 说,C0 控制字符在 U+0000—U+001F 和 U+007F 范围内(与 ASCII 范围相同),C1 控制字符在 U+0080—U+009F 范围内

除了 C 控制字符,Unicode 还有数百个格式化控制字符,例如零宽度非连接符,使字符间距更近,或双向文本控制。这种格式控制字符比较分散。

更重要的是,你在做什么需要你知道 Unicode 的不可打印字符?很可能,无论您尝试做什么,解决问题的方法都是错误的。

【讨论】:

我想创建一个随机的 unicode 字符串生成器,它将生成可打印的字符。 可由谁打印?你想包括例如。所有的汉字?许多用户没有字体,因此“打印”它们不会给你任何东西,一个空白框或其他一些无用的替换字符。 一个很好的理由是避免安全漏洞:bugzilla.mozilla.org/show_bug.cgi?id=968576 @bobince 我的浏览器可以显示汉字。但不确定 2010 年是否是这种情况。 “你在做什么需要你知道 Unicode 的不可打印字符?” 用户将 Windows 计算器中的数字粘贴到文本框中(例如 ‭165063688192‬)。但实际上该字符串将是:U+202D165063688192U+202C。因此,字符串将是不可解析的,没有人能够找出原因。多亏了一个没人想要的功能:我们现在需要编写 TrimStrimToPrintable(String s) 函数。【参考方案2】:

首先,您应该删除问题中的“UTF8”一词,它不相关(UTF8 只是 Unicode 的编码之一,它与您的问题正交)。

第二:“可打印/不可打印”的含义在 Unicode 中不太清楚。也许您的意思是 "graphical character" ;如果一个空间是可打印的/图形的,人们甚至可以争论。非图形字符基本上由控制字符组成:0x00-0x0f 范围加上其他一些分散的字符。

无论如何,绝大多数 Unicode 字符(超过 200.000 个)都是“图形的”。但这当然并不意味着它们可以在您的环境中打印。

在我看来,如果您打算生成一个“随机可打印”的 unicode 字符串,那么尝试包含所有“可打印”字符是个坏主意。

【讨论】:

【参考方案3】:

这是一个古老的问题,但它仍然有效,我认为除了现有答案所涵盖的主题之外,还有更多有用但简要的说明。

Unicode

Unicode 定义properties for characters。

其中一个属性是“General Category”,它具有主要类和子类。主要类别是字母、标记、标点符号、符号、分隔符和其他。

通过了解角色的属性,您可以决定是否认为它们可在您的特定环境中打印

您必须始终记住,“字符”和“可打印”之类的术语通常很困难,并且有一些有趣的极端情况。


编程语言支持

一些编程语言可以帮助解决这个问题。

例如,Go 语言有一个“unicode”包,它提供了许多有用的与 Unicode 相关的功能,包括这两个:

func IsGraphic(r rune) bool

IsGraphic reports whether the rune is defined as a Graphic by Unicode. Such  
characters include letters, marks, numbers, punctuation, symbols, and spaces, 
from categories L, M, N, P, S, Zs. 

func IsPrint(r rune) bool

IsPrint reports whether the rune is defined as printable by Go. Such  
characters include letters, marks, numbers, punctuation, symbols, and  
the ASCII space character, from categories L, M, N, P, S and the ASCII  
space character. This categorization is the same as IsGraphic except  
that the only spacing character is ASCII space, U+0020.

请注意,它说的是“由 Go 定义为可打印”,而不是“由 Unicode 定义为可打印”。就好像 Unicode 的巫师们有一些不敢深究的深度。


可打印

您对 Unicode 了解得越多,就越能意识到人类书写系统的多样性和不可思议的怪异程度。

尤其是特定的“字符”是否可打印并不总是显而易见的。

可以打印零宽度空间吗?什么时候可以打印断字点?是否有字符的可打印性取决于它们在单词中的位置或与它们相邻的字符?组合字符总是可打印的吗?


脚注

ASCII 可打印字符范围为 \u0020 - \u007f

不,不是。 \u007f 是 DEL,通常不被视为可打印字符。例如,它与标有“DEL”的键盘键相关联,该键最早的用途是命令从某种介质(显示器、文件等)中删除字符。

事实上,许多 8 位字符集有许多不可打印的非连续范围。参见例如 C0 和 C1 控件。

【讨论】:

DEL 被标记为 RUBOUT 时更有趣(在我很久以前开始使用的 TTY 上)。【参考方案4】:

您应该选择一种字体,然后生成一个列表,其中列出了哪些 Unicode 字符为您的字体定义了字形。您可以使用 freetype 之类的字体库来测试字形(测试 FT_Get_Char_Index(...) != 0)。

【讨论】:

【参考方案5】:

对@HoldOffHunger 采取相反的方法,可能更容易列出不可打印字符的范围,并使用not 来测试字符是否可打印。

采用正则表达式的样式(因此,如果您想要可打印字符,请放置^):

[\u0000-\u0008\u000B-\u001F\u007F-\u009F\u2000-\u200F\u2028-\u202F\u205F-\u206F\u3000\uFEFF]

separator spaces 和 joiners 之类的原因

请注意,与他们的答案不同的是,他们的答案是一个忽略所有非拉丁语言的白名单,这个黑名单不会仅仅因为它们在块中就允许不可打印字符 可打印字符(他们的答案完全包括Non-Latin, Language Supplement blocks 为“可打印”,即使它包含诸如“零宽度非连接器”之类的内容..)。

但请注意,如果使用此解决方案或任何其他解决方案,例如卫生,您可能需要做一些比更换毯子更细微的事情。 可以说在这种情况下,non-breaking spaces 应该更改为space,而不是被删除,invisible separator 应该替换为逗号有条件地

然后有无效的字符范围,[尚未]未使用或保留用于编码目的,以及language-specific variation selectors..


注意,使用正则表达式时,如果默认情况下不是这样,则启用 unicode 感知(对于 javascript,它是通过 /.../u)。

您可以通过尝试使用一些多字节字符范围创建正则表达式来判断它是否正确。 比如上面,加上javascript中的无效字符范围\uE0100-\uE01EF

/[\u0000-\u0008\u000B-\u001F\u007F-\u009F\u2000-\u200F\u2028-\u202F\u205F-\u206F\u3000\uFEFF\uE0100-\uE01EF]/u

没有u \uE0100-\uE01EF 等于\uDB40(\uDD00-\uDB40)\uDDEF,而不是(\uDB40\uDD00)-(\uDB40\uDDEF),如果替换你应该始终启用u,即使在正则表达式本身中不包含多字节unicode,因为你可能会破坏存在的surrogate pairs在正文中。

【讨论】:

【参考方案6】:

哪些字符有效?

目前,Unicode 被定义为从U+0000 开始,到U+10FFFF 结束。第一个区块,Basic Latin,跨越 U+0000U+007F,最后一个区块,Supplementary Private Use Area-B,跨越 U+10000010FFFF。如果您想查看所有这些块,请参见此处:Wikipedia.org: Unicode Block; List of Blocks。

让我们分解一下拉丁语 Block1 中的有效/无效内容。

拉丁语块:TLDR

如果您有兴趣过滤掉任何一个不可见字符,您需要过滤掉:

U+0000U+0008:控制 U+000EU+001F:设备(即控制) U+007F:删除(控制) U+008DU+009F:设备(即控制)

拉丁语块:全范围

这是拉丁语块,分成更小的部分...

U+0000U+0008:控制 U+0009U+000C:空格 U+000EU+001F:设备(即控制) U+0020:空格 U+0021U+002F:符号 U+0030U+0039:数字 U+003AU+0040:符号 U+0041U+005A:大写字母 U+005BU+0060:符号 U+0061U+007A:小写字母 U+007BU+007E:符号 U+007F:删除(控制) U+0080U+008C:Latin1-补充符号。 U+008DU+009F:设备(即控制) U+00A0:不间断空间。 (即 U+00A1U+00BF:符号。 U+00C0U+00FF:重音字符。

其他方块

Unicode 以支持非拉丁字符集而闻名,那么这些其他块是什么?这只是一个粗略的概述,请参阅wikipedia.org page 了解完整的完整列表。

Latin1 和 Latin1 相关块

U+0000U+007F :基本拉丁语 U+0080U+00FF:拉丁语 1 补充 U+0100U+017F :拉丁语扩展-A U+0180U+024F :拉丁文扩展-B

可组合块

U+0250U+036F:3 块。

非拉丁语,语言块

U+0370U+1C7F:55 块。

非拉丁语,语言补充块

U+1C80U+209F:11 块。

符号块

U+20A0U+2BFF:22 块。

古语块

U+2C00U+2C5F:1 块(格拉哥里)。

语言扩展块

U+2C60U+FFEF:66 块。

特殊方块

U+FFF0U+FFFF:1 块(特价)。

【讨论】:

【参考方案7】:

一种方法是将每个字符渲染到纹理并手动检查它是否可见。此解决方案不包括空格。

我编写了这样一个程序,并用它来确定前 471859 个代码点中大约有 467241 个可打印字符。我选择了这个数字,因为它涵盖了 Unicode 的所有前 4 个平面,它们似乎包含所有可打印字符。见https://en.wikipedia.org/wiki/Plane_(Unicode)

我很想改进我的程序以生成 范围列表,但现在我正在为任何需要立即得到答案的人提供以下解决方案:

https://editor.p5js.org/SamyBencherif/sketches/_OE8Y3kS9

我发布这个工具是因为我认为这个问题吸引了很多人,他们正在寻找了解可打印范围的稍微不同的应用程序。希望这是有用的,即使它没有完全回答问题。

【讨论】:

【参考方案8】:

在 int 数据类型中,可打印的 Unicode 字符范围(不包括十六进制)为 32 到 126。

【讨论】:

这种说法显然是错误的;在撰写本文时,Unicode 有近 150,000 个可打印符号(Unicode 13.0)。见en.wikipedia.org/wiki/Unicode。【参考方案9】:

Unicode,固定术语,没有范围。数字可以无限。

您提供的不是 UTF8,它有 1 个字节用于 ASCII 字符。

至于范围,我相信没有可打印字符的范围。它总是在进化。检查我上面给出的页面。

【讨论】:

Afaik Unicode 仅在 0x10ffff 之前定义,除此之外不会分配任何代码点

以上是关于Unicode 可打印字符的范围是多少?的主要内容,如果未能解决你的问题,请参考以下文章

测试utf-8 汉字和字符等一般占多少个字节

Python 字符集编码 - UTF-8 编码

Unicode(统一码万国码单一码)

中文字符替换为其unicode编码值小3的字符

PHP字符串中的Unicode字符

unicode编码详解,一看就懂