Unicode可打印字符的范围是什么?

66

请问Unicode可打印字符的范围是什么?[例如,Ascii可打印字符的范围是\u0020-\u007f]


2
\u0000 - \u0020 在 Unicode 中也是不可打印的。 - Andrey
7
更像是从空格到波浪符之间的字符。 - Desmond Hume
3
你对这个问题确实遭到了很多批评。我喜欢这个想法。 - jsejcksn
使用编程语言符号表示UTF-16代码单元来给出ASCII码点范围有些奇怪(但从数字和字符方面来看,确实可行)。 - Tom Blodget
1
这个问题非常简单明了,但答案却不是那么简单。因此自然而然地,每个人都会声称这个问题是无效的。这是一个关于Unicode而不是字体(afaik)的问题,因此重要的是符号在概念上是否可以被绘制。控制字符、零宽字符和修饰符显然不包括在此列表中。 \u0020和其他空格(?)是一个边缘情况,但这并不意味着这个问题无法回答。无论如何,我建议访问https://en.wikipedia.org/wiki/List_of_Unicode_characters以进一步研究此事。 - Samie Bencherif
9个回答

25

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

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

维基百科表示,C0控制字符的范围为U+0000—U+001F和U+007F(与ASCII相同),C1控制字符的范围为U+0080—U+009F

除了C控制字符之外,Unicode还有数百个格式控制字符,例如零宽度非连接符,可以使字符间距更紧密,或者双向文本控制字符。这些格式控制字符比较分散。

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


10
我想创建一个随机Unicode字符串生成器,它将生成可打印字符。 - Anindya Chatterjee
7
谁可以进行打印?您是否想要包含所有的中文字符?许多用户可能没有相应的字体,因此“打印”它们将得到空白框或其他无用的替换字符。 - bobince
7
一个好的理由是避免安全漏洞:https://bugzilla.mozilla.org/show_bug.cgi?id=968576 - Neil McGuigan
4
你需要知道Unicode的非打印字符是做什么的?用户将Windows计算器中的数字粘贴到文本框中(例如 165063688192),但实际上该字符串将包含:U+202D165063688192U+202C。因此,该字符串无法解析,没有人能够弄清原因。所以,由于没有人想要的功能,我们现在需要编写TrimStrimToPrintable(String s)函数。 - Ian Boyd
根据您提供的维基百科页面,0x7F不属于C0控制字符范围。您能否澄清一下? - SOFe
显示剩余2条评论

22
这是一个老问题,但仍然有效,我认为有更多有用的东西需要简洁地说一下这个主题,而不是现有答案所涵盖的内容。
Unicode定义了字符属性
其中之一是“一般类别”,它具有主类和子类。主要类别包括字母、标记、标点、符号、分隔符和其他。
通过了解您的字符属性,您可以决定是否在特定上下文中将它们视为可打印。
您必须始终记住,“字符”和“可打印”等术语通常很难,并且有有趣的边缘情况。

编程语言支持

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

例如,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控件。


1
当我很久以前开始使用TTY时,DEL被标记为RUBOUT,这使它更有趣。 - James Craig Burley

18

首先,你应该在问题中删除“UTF8”这个词,它与你的问题无关(UTF8只是Unicode编码中的一种编码方式,与你的问题无关)。

其次,在Unicode中,“可打印/不可打印”的含义不太清楚。也许你指的是 "图形字符";甚至可以争论空格是否可打印/可画出。非图形字符基本上由控制字符组成:范围为0x00-0x0f加上一些零散的字符。

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

如果你打算生成一个“随机可打印”的Unicode字符串,尝试包括所有“可打印”的字符似乎是一个坏主意。


6
你需要做的是选择一种字体,然后生成一个列表,列出哪些Unicode字符在你的字体中有定义的字形。你可以使用像freetype这样的字体库来测试字形(测试FT_Get_Char_Index(...) != 0)。

5

哪些字符是有效的?

目前,Unicode 的定义从 U+0000 开始,到 U+10FFFF 结束。第一个块,基本拉丁字母,跨越了 U+0000U+007F,而最后一个块,补充专用区-B,跨越了 U+10000010FFFF。如果您想查看所有这些块,请参见此处:Wikipedia.org: Unicode Block; List of Blocks

让我们来分析一下拉丁字母块中什么是有效/无效的。

拉丁字母块:简述

如果您想要过滤掉不可见字符,您需要过滤掉以下内容:

  • 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-Supplement 符号。
  • 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个块(特殊字符)。


3
采用与@HoldOffHunger相反的方法,可能更容易列出不可打印字符的范围,并使用not来测试一个字符是否可打印。
按照正则表达式的风格(因此如果您想要可打印字符,请放置一个^):
[\u0000-\u0008\u000B-\u001F\u007F-\u009F\u2000-\u200F\u2028-\u202F\u205F-\u206F\u3000\uFEFF]

这包括了像分隔空格连接符这样的内容。

请注意,与它们的白名单不同,该黑名单不会允许非拉丁语言,即使它们与可打印字符(他们的答案完全将非拉丁语言补充块视为“可打印”,即使其中包含诸如“零宽度非连接符”之类的东西…)。

但要注意,如果使用此或任何其他解决方案进行净化,则可能需要执行比简单替换更为细致的操作。
在这种情况下,可以将不间断空格更改为空格,而不是删除它,并且可以有条件地将不可见分隔符替换为逗号。

还有无效的字符范围,未被使用或保留用于编码目的,以及特定于语言的变体选择器


当使用正则表达式时,请确保启用了Unicode,如果默认情况下未启用(例如对于JavaScript,则通过/.../u实现)。

您可以尝试使用一些多字节字符范围创建正则表达式以确定是否正确,例如上面的例子加上无效字符范围\u{E0100}-\u{E01EF}在JavaScript中:

/[\u0000-\u0008\u000B-\u001F\u007F-\u009F\u2000-\u200F\u2028-\u202F\u205F-\u206F\u3000\uFEFF\u{E0100}-\u{E01EF}]/u

Unicode RegExp

在没有u标志的情况下,\u{E0100}-\u{E01EF}等同于\uDB40(\uDD00-\uDB40)\uDDEF,而不是(\uDB40\uDD00)-(\uDB40\uDDEF)。如果替换时,应始终启用u标志,即使正则表达式本身不包含多字节Unicode字符,因为这可能会破坏文本中存在的代理对


0
一种方法是将每个字符渲染到纹理中并手动检查其是否可见。该解决方案不包括空格。
我编写了这样一个程序,并使用它确定了在前471859个代码点中有大约467241个可打印字符。我选择了这个数字,因为它涵盖了Unicode的前4个平面,这些平面似乎包含了所有可打印字符。请参见https://en.wikipedia.org/wiki/Plane_(Unicode)
我非常希望完善我的程序,以生成范围列表,但现在对于任何需要即时答案的人,这就是我正在使用的内容。

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

我发布这个工具是因为我认为这个问题吸引了很多寻找可打印范围稍有不同应用的人。希望这对你有所帮助,尽管它并没有完全回答这个问题。

-4

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


1
这个说法显然是错误的;在撰写本文时,Unicode 已经有将近 150,000 个可打印符号(Unicode 13.0)。请参见 https://en.wikipedia.org/wiki/Unicode。 - ti7

-9

Unicode,是一种严格的术语,没有范围限制。数字可以无限大。

你提供的不是UTF8编码,它对ASCII字符只有1个字节。

至于范围,我相信没有可打印字符的范围。它总是在发展变化中。请查看我上面提供的页面。


9
据我所知,Unicode 只定义到 0x10ffff,超出这个范围将不会分配任何代码点。 - Sebastian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接