如何在Python中获得组合Unicode字符串的“可见”长度?

时间:2015-10-26 17:10:29

标签: python python-2.7 unicode

如果我有一个包含组合字符的Python Unicode字符串,len会报告一个与“看到”字符数不对应的值。

例如,如果我有一个组合上划线和下划线的字符串,例如u'A\u0332\u0305BC'len(u'A\u0332\u0305BC')报告5;但显示的字符串只有3个字符。

如何获得“可见” - 即用户看到的字符串占用的不同位置的数量 - 包含Python中组合字形的Unicode字符串的长度?

3 个答案:

答案 0 :(得分:4)

unicodedata module有一个函数combining,可用于确定单个字符是否为组合字符。如果它返回0,您可以将该字符计为非合并。

import unicodedata
len(u''.join(ch for ch in u'A\u0332\u0305BC' if unicodedata.combining(ch) == 0))

或者,稍微简单一些:

sum(1 for ch in u'A\u0332\u0305BC' if unicodedata.combining(ch) == 0)

答案 1 :(得分:4)

如果您的正则表达式支持匹配grapheme,则可以使用ApplicationDbContext

Demo

虽然默认的Python re模块不支持\X,但Matthew Barnett的regex module却支持:

\X

在Python 2上,您需要在模式中使用>>> len(regex.findall(r'\X', u'A\u0332\u0305BC')) 3

u

答案 2 :(得分:2)

组合字符不是唯一的零宽度字符:

>>> sum(1 for ch in u'\u200c' if unicodedata.combining(ch) == 0)
1

"\u200c""‌"为零宽度非连接符;它是非打印字符。)

在这种情况下,正则表达式模块也不起作用:

>>> len(regex.findall(r'\X', u'\u200c'))
1

我发现wcwidth正确处理了上述情况:

>>> from wcwidth import wcswidth
>>> wcswidth(u'A\u0332\u0305BC')
3
>>> wcswidth(u'\u200c')
0

但似乎仍无法使用用户596219的示例:

>>> wcswidth('각')
4