如何在Python 3.x中确定Unicode字符串的显示宽度,是否可以使用该信息将这些字符串与str.format()
对齐?
激励示例:将字符串表打印到控制台。某些字符串包含非ASCII字符。
>>> for title in d.keys():
>>> print("{:<20} | {}".format(title, d[title]))
zootehni- | zooteh.
zootekni- | zootek.
zoothèque | zooth.
zooveterinar- | zoovet.
zoovetinstitut- | zoovetinst.
母 | 母母
>>> s = 'è'
>>> len(s)
2
>>> [ord(c) for c in s]
[101, 768]
>>> unicodedata.name(s[1])
'COMBINING GRAVE ACCENT'
>>> s2 = '母'
>>> len(s2)
1
可以看出,str.format()
只是将字符串(len(s)
)中的代码点数作为其宽度,从而导致输出中的列偏斜。通过unicodedata
模块搜索,我找不到任何建议解决方案。
Unicode规范化可以解决è的问题,但不适用于通常具有较大显示宽度的亚洲字符。类似地,存在零宽度的unicode字符(例如,用于允许字内的换行的零宽度空间)。您无法通过规范化解决这些问题,因此请不要建议“规范化字符串”。
修改:添加了有关规范化的信息。
编辑2:在我的原始数据集中,还有一些欧洲组合字符,即使在规范化后也不会产生单个代码点:
zwemwater | zwemw.
zwia̢z- | zw.
>>> s3 = 'a\u0322' # The 'a + combining retroflex hook below' from zwiaz
>>> len(unicodedata.normalize('NFC', s3))
2
答案 0 :(得分:2)
您有几种选择:
某些控制台支持转义序列,用于像素精确定位光标。不过可能会导致一些叠印。
历史记录:这种方法在Amiga终端中用于在控制台窗口中显示图像,方法是打印一行文本,然后将光标向下推进一个像素。文本行的剩余像素慢慢构建了一个图像。
在代码中创建一个表,其中包含控制台/终端窗口中使用的字体中所有Unicode字符的实际(像素)宽度。使用UI框架和一个小的Python脚本来生成此表。
然后添加使用此表计算文本实际宽度的代码。但结果可能不是控制台中字符宽度的倍数。与像素精确的光标移动一起,这可以解决您的问题。
注意:您必须为连字(fi,fl)和composites添加特殊处理。或者,您可以在不打开窗口的情况下加载UI框架,并使用图形基元来计算字符串宽度。
使用制表符(\t
)缩进。但是,只有在shell实际使用实际文本宽度放置光标时,这才有用。许多终端只会计算字符数。
使用表创建一个HTML文件,并在浏览器中查看。