我需要知道包含日文/中文字符的unicode字符串中有多少可显示的字符。
示例代码使问题非常明显:
# -*- coding: UTF-8 -*-
str = '\xe7\x9d\xa1\xe7\x9c\xa0\xe6\x99\x82\xe9\x96\x93'
print len(str)
12
print str
睡眠时间<<< 请注意显示四个字符
我怎么能从字符串中知道将要显示4个字符?
答案 0 :(得分:8)
此字符串
str = '\xe7\x9d\xa1\xe7\x9c\xa0\xe6\x99\x82\xe9\x96\x93'
是 unicode代码点的编码表示。它包含字节,len(str)返回 bytes 的数量。
您想知道,有多少个unicode代码包含该字符串。为此,您需要知道,使用了哪些编码来编码这些unicode代码。最受欢迎的编码是 utf8 。在utf8编码中,一个unicode代码点可以占用1到6个字节。但你不能记住,只需解码字符串:
>>> str.decode('utf8')
u'\u7761\u7720\u6642\u9593'
在这里你可以看到4个unicode点。 打印它,看看可打印的版本:
>>> print str.decode('utf8')
睡眠時間
获取unicode代码的数量:
>>> len(str.decode('utf8'))
4
更新:同时注意abarnert answer以尊重所有可能的情况。
答案 1 :(得分:3)
如果你真的想要“可显示的字符”,你必须做两件事。
首先,您必须将字符串从UTF-8转换为Unicode,如stalk:
所述s = '\xe7\x9d\xa1\xe7\x9c\xa0\xe6\x99\x82\xe9\x96\x93'
u = s.decode('utf-8')
接下来,您必须过滤掉所有不代表可显示字符的代码点。您可以使用unicodedata
模块。 category
函数可以为您提供任何代码单元的常规类别。要了解这些类别,请查看从您的Python unicodedata
文档版本链接的Unicode字符数据库版本中的General Categories table。
对于使用UCD 5.2.0的Python 2.7.8,你必须做一些解释来决定什么算作“可显示”,因为Unicode实际上没有任何对应于“可显示”的东西。但是,假设您已经确定所有控件,格式,私有和未分配的字符都不可显示,而其他所有字符都是可显示的。然后你会写:
def displayable(c):
return unicodedata.category(c).startswith('C')
p = u''.join(c for c in u if displayable(c))
或者,如果你已经确定Mn和Me也不是“可显示的”,那么Mc就是:
def displayable(c):
return unicodedata.category(c) in {'Mn', 'Me', 'Cc', 'Cf', 'Co', 'Cn'}
但即使这可能不是你想要的。例如,非标点组合标记后跟字母是否计为一个或两个字符?标准示例是U + 0043加U + 0327:构成一个字符的两个代码点,Ç(但U + 00C7也是单个代码点中的相同字符)。通常情况下,恰当地正常化你的字符串(通常意味着NKFC或NKFD)足以解决这个问题 - 一旦你知道你想要什么答案。当然,除非你能回答这个问题,否则没有人能告诉你如何去做。
如果您正在考虑,“这很糟糕,应该有'可打印'的官方定义,并且Python应该知道该定义”,嗯,他们这样做,您只需要使用更新版本的Python。在3.x中,你可以写:
p = ''.join(c for c in u is c.isprintable())
但当然,只有当他们对“可打印”的定义恰好与“可显示”的含义相符时才有效。而且很可能不会 - 例如,他们认为除' '
之外的所有分隔符都是不可打印的。显然,他们不能包含任何人可能想要区别的定义。