我想创建一个Unicode代码点数组,这些代码点构成JavaScript中的空白区域(减去我分别处理的Unicode白空间代码点)。这些字符包括水平制表符,垂直制表符,换页符,空格,不间断空格和BOM。我可以用魔术数字来做到这一点:
whitespace = [0x9, 0xb, 0xc, 0x20, 0xa0, 0xfeff]
这有点模糊;名字会更好。通过unicodedata.lookup
传递的ord
方法有助于某些方法:
>>> ord(unicodedata.lookup("NO-BREAK SPACE"))
160
但这不适用于0x9,0xb或0xc - 我认为因为它们是控制字符,而“名称”FORM FEED等只是别名。有没有办法将这些“名称”映射到标准Python中的字符或其代码点?或者我运气不好?
答案 0 :(得分:13)
Kerrek SB的评论很好:只需将名字放在评论中即可。
BTW,Python还支持命名的unicode文字:
>>> u"\N{NO-BREAK SPACE}"
u'\xa0'
但是它使用相同的unicode名称数据库,并且控制字符不在其中。
答案 1 :(得分:2)
您可以通过解析Unicode public directory中的几行UCD文件来为控制字符滚动自己的“数据库”。特别是,请参阅UnicodeData-6.1.0d3文件(或查看早期版本的父目录)。
答案 2 :(得分:2)
我不认为它可以在标准Python中完成。 unicodedata
模块使用UnicodeData.txt v5.2.0 Unicode数据库。请注意,控制字符都分配了名称<control>
(第二个字段,以分号分隔)。
Python源代码分发中的脚本Tools/unicode/makeunicodedata.py
用于生成Python运行时使用的表。 makeunicodename
函数如下所示:
def makeunicodename(unicode, trace):
FILE = "Modules/unicodename_db.h"
print "--- Preparing", FILE, "..."
# collect names
names = [None] * len(unicode.chars)
for char in unicode.chars:
record = unicode.table[char]
if record:
name = record[1].strip()
if name and name[0] != "<":
names[char] = name + chr(0)
...
请注意,它会跳过名称以"<"
开头的条目。因此,没有名称可以传递给unicodedata.lookup
,而这些名称会返回给其中一个控制字符。
只需对水平制表符,换行符和回车符的代码点进行硬编码,然后留下描述性注释。正如Zen of Python所说,“实用性胜过纯洁”。
答案 3 :(得分:1)
几点:
(1)“BOM”不是一个字符。 BOM是一个出现在文件开头的字节序列,用于指示以UTF-nn编码的文件的字节顺序。 BOM是你'\ uFEFF'.encode('UTF-nn')。使用适当的编解码器读取文件将会破坏BOM;你不认为它是一个Unicode字符。 BOM不是数据。如果您确实在数据中看到了'\ uFEFF',请将其视为(已弃用)ZERO-WIDTH NO-BREAK SPACE。
(2)“减去Unicode-white-space代码点,我单独解决”?不是NO-BREAK SPACE是一个“Unicode-white-space”代码点?
(3)你的Python似乎被打破了;我这样做:
>>> ord(unicodedata.lookup("NO-BREAK SPACE"))
160
(4)你可以使用前三个的转义序列。
>>> map(hex, map(ord, "\t\v\f"))
['0x9', '0xb', '0xc']
(5)您可以使用" "
作为第四个。
(6)即使你可以使用名字,你的代码的读者仍然会盲目相信,例如: “FORM FEED”是一个空格字符。
(7)\r
和\n
发生了什么?
答案 4 :(得分:0)
假设您正在使用Unicode字符串,则在使用正则表达式时,列表中的前五项以及所有其他Unicode空格字符将与\s
选项匹配。使用Python 3.1.2:
>>> import re
>>> s = '\u0009,\u000b,\u000c,\u0020,\u00a0,\ufeff'
>>> s
'\t,\x0b,\x0c, ,\xa0,\ufeff'
>>> re.findall(r'\s', s)
['\t', '\x0b', '\x0c', ' ', '\xa0']
至于字节顺序标记,给定的标记可以称为codecs.BOM_BE
或codecs.BOM_UTF16_BE
(尽管在Python 3+中,它作为bytes
对象返回,而不是str
)。
答案 5 :(得分:0)
新行的official Unicode recommendation可能与Python codecs
模块处理换行符的方式不一致。由于u'\n'
通常被称为“新行”,因此人们可能会根据此建议将Python字符串u'\n'
表示为字符U+2028 LINE SEPARATOR
并按此编码,而不是无语义控制字符U+000A
。但我只能想象如果codecs
模块实际实现了该策略会产生的混淆,并且除此之外还有有效的反驳。同样适用于水平/垂直制表符和换页符,它们可能不是真正的字符,但无论如何都要控制。 (我当然会认为退格是一个控件,而不是一个角色。)
您的问题似乎假设将U+000A
视为控制字符(而不是行分隔符)是错误的;但这完全不确定。对于各地的文本处理应用程序而言,假设传统的打印机压板滚动控制信号确实是真正的“行分隔符”可能更为错误。
答案 6 :(得分:-1)
您可以扩展查找功能以处理未包含的字符。
def unicode_lookup(x):
try:
ch = unicodedata.lookup(x)
except KeyError:
control_chars = {'LINE FEED':unichr(0x0a),'CARRIAGE RETURN':unichr(0x0d)}
if x in control_chars:
ch = control_chars[x]
else:
raise
return ch
>>> unicode_lookup('SPACE')
u' '
>>> unicode_lookup('LINE FEED')
u'\n'
>>> unicode_lookup('FORM FEED')
Traceback (most recent call last):
File "<pyshell#17>", line 1, in <module>
unicode_lookup('FORM FEED')
File "<pyshell#13>", line 3, in unicode_lookup
ch = unicodedata.lookup(x)
KeyError: "undefined character name 'FORM FEED'"