谁能告诉我 Unicode 可打印字符的范围是多少?[例如 Ascii 可打印字符范围是 \u0020 - \u007f]
9 回答
见,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 的不可打印字符?很可能,无论您尝试做什么,解决问题的方法都是错误的。
首先,您应该删除问题中的“UTF8”一词,它不相关(UTF8 只是 Unicode 的编码之一,它与您的问题正交)。
第二:Unicode中“可打印/不可打印”的含义不太清楚。也许您的意思是“图形字符”;如果一个空间是可打印的/图形的,人们甚至可以争论。非图形字符基本上由控制字符组成:范围 0x00-0x0f 加上其他一些分散的字符。
无论如何,绝大多数 Unicode 字符(超过 200.000 个)都是“图形的”。但这当然并不意味着它们可以在您的环境中打印。
在我看来,如果您打算生成一个“随机可打印”的 unicode 字符串来尝试包含所有“可打印”字符,那么这似乎是一个坏主意。
这是一个古老的问题,但它仍然有效,我认为关于这个主题还有更多有用但简短的说法,而不是现有答案所涵盖的内容。
统一码
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 控件。
您应该做的是选择一种字体,然后生成一个列表,其中列出了哪些 Unicode 字符为您的字体定义了字形。您可以使用像 freetype 这样的字体库来测试字形(测试 FT_Get_Char_Index(...) != 0)。
对@HoldOffHunger 采取相反的方法,列出不可打印字符的范围可能更容易,并用于not
测试字符是否可打印。
以 Regex 的风格(因此,如果您想要可打印的字符,请放置 a ^
):
[\u0000-\u0008\u000B-\u001F\u007F-\u009F\u2000-\u200F\u2028-\u202F\u205F-\u206F\u3000\uFEFF]
请注意,与他们的答案不同,这是一个忽略所有非拉丁语言的白名单,这个黑名单不会仅仅因为它们位于带有可打印字符的块中而允许不可打印的字符(他们的答案完全包括Non-Latin, Language Supplement blocks
“可打印”,即使它包含东西像'零宽度非连接器'..)。
但是请注意,如果使用此解决方案或任何其他解决方案,例如卫生,您可能想做一些比更换毯子更细微的事情。
可以说在这种情况下,non-breaking space
s 应该更改为space
,而不是被删除,并且invisible separator
应该有条件地用逗号替换。
然后是无效的字符范围,[尚未]未使用或保留用于编码目的,以及特定于语言的变体选择器..
注意使用正则表达式时,如果默认情况下不是这样,您可以启用 unicode 感知(对于 javascript,它是 via /.../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
如果没有u
\u{E0100}-\u{E01EF}
equates \uDB40(\uDD00-\uDB40)\uDDEF
, not (\uDB40\uDD00)-(\uDB40\uDDEF)
,并且如果替换,u
即使在正则表达式本身中不包含多字节 unicode 时,您也应该始终启用,因为您可能会破坏文本中存在的代理对。
哪些字符是有效的?
目前,Unicode 被定义为从 开始U+0000
和结束于U+10FFFF
. 第一个块Basic Latin跨越U+0000
到U+007F
,最后一个块Supplementary Private Use Area-B跨越U+100000
到10FFFF
。如果您想查看所有这些块,请参见此处:Wikipedia.org: Unicode Block;块列表。
让我们分解一下拉丁语 Block1 中的有效/无效内容。
拉丁区:TLDR
如果您有兴趣过滤掉任何一个不可见的字符,您需要过滤掉:
U+0000
至U+0008
:控制U+000E
toU+001F
:设备(即控制)U+007F
:删除(控制)U+008D
toU+009F
:设备(即控制)
拉丁区:全范围
这是拉丁语块,分成更小的部分......
U+0000
至U+0008
:控制U+0009
至U+000C
:空间U+000E
toU+001F
:设备(即控制)U+0020
: 空间U+0021
至U+002F
:符号U+0030
至U+0039
:数字U+003A
至U+0040
:符号U+0041
toU+005A
: 大写字母U+005B
至U+0060
:符号U+0061
toU+007A
: 小写字母U+007B
至U+007E
:符号U+007F
:删除(控制)U+0080
toU+008C
:Latin1-补充符号。U+008D
toU+009F
:设备(即控制)U+00A0
: 非破坏空间。(即,
)U+00A1
到U+00BF
:符号。U+00C0
toU+00FF
:重音字符。
其他方块
Unicode 以支持非拉丁字符集而闻名,那么这些其他块是什么?这只是一个广泛的概述,请参阅wikipedia.org 页面以获取完整的完整列表。
Latin1 和 Latin1 相关块
U+0000
toU+007F
: 基本拉丁语U+0080
toU+00FF
: Latin-1 补充U+0100
toU+017F
: 拉丁语扩展-AU+0180
toU+024F
: 拉丁语扩展-B
可组合块
U+0250
至U+036F
:3 块。
非拉丁语,语言块
U+0370
至U+1C7F
:55 块。
非拉丁语,语言补充块
U+1C80
至U+209F
:11 个街区。
符号块
U+20A0
至U+2BFF
:22 块。
古代语言块
U+2C00
至U+2C5F
:1 块(格拉哥里)。
语言扩展块
U+2C60
至U+FFEF
:66 块。
特殊块
U+FFF0
至U+FFFF
:1 块(特价)。
一种方法是将每个字符渲染到纹理并手动检查它是否可见。此解决方案不包括空格。
我编写了这样一个程序,并用它来确定前 471859 个代码点中大约有467241 个可打印字符。我选择了这个数字,因为它涵盖了 Unicode 的所有前 4 个平面,它们似乎包含所有可打印字符。见https://en.wikipedia.org/wiki/Plane_(Unicode)
我很想改进我的程序以生成范围列表,但现在我正在为任何需要立即答案的人使用:
https://editor.p5js.org/SamyBencherif/sketches/_OE8Y3kS9
我发布这个工具是因为我认为这个问题吸引了很多人,他们正在寻找了解可打印范围的稍微不同的应用程序。希望这是有用的,即使它没有完全回答这个问题。
在 int 数据类型中,可打印的 Unicode 字符范围(不包括十六进制)是 32 到 126。