我怎样才能从len(),str.format()和零宽度空间中获得合理的结果



我正在尝试格式化表格中的文本并将结果写入文件,但我的对齐方式有问题,因为我的源代码有时包含 Unicode 字符"零宽度空间"或 python 中的u200b。请考虑以下代码示例:

str_list = ("au200bu200b", "b", "longest entryu200b")
format_str = "|{string:<{width}}| output of len(): {length}n"
max_width = 0
for item in str_list:
    if len(item) > max_width:
        max_width = len(item)
with open("tmp", mode='w', encoding="utf-8") as file:
    for item in str_list:
        file.write(format_str.format(string=item,
                                     width=max_width,
                                     length=len(item)))

运行上述脚本后"tmp"的内容:

|a​​           | output of len(): 3
|b             | output of len(): 1
|longest entry​| output of len(): 14

所以这看起来len()不会导致字符串的"打印宽度",并且str.format()不知道如何处理零宽度字符。

或者,这种行为是故意的,我需要做其他事情。

需要明确的是,我正在寻找一种方法来获得这样的结果:

|a​​            | output of len(): 1
|b            | output of len(): 1
|longest entry​| output of len(): 13

如果可以不破坏我的来源,我宁愿这样做。

wcwidth 包有一个函数 wcswidth() 它返回字符单元格中字符串的宽度:

from wcwidth import wcswidth
length = len('sneakyu200bPete')      # 11
width = wcswidth('sneakyu200bPete')  # 10

然后,可以使用wcswidth(s)len(s)之间的差异来更正str.format()引入的错误。修改上面的代码:

from wcwidth import wcswidth
str_list = ("au200bu200b", "b", "longest entryu200b")
format_str = "|{s:<{fmt_width}}| width: {width}, error: {fmt_error}n"
max_width = max(wcswidth(s) for s in str_list)
with open("tmp", mode='w', encoding="utf-8") as file:
    for s in str_list:
        width = wcswidth(s)
        fmt_error = len(s) - width
        fmt_width = max_width + fmt_error
        file.write(format_str.format(s=s,
                                     fmt_width=fmt_width,
                                     width=width,
                                     fmt_error=fmt_error))

。生成以下输出:

|a​​            | width: 1, error: 2
|b            | width: 1, error: 0
|longest entry​| width: 13, error: 1

它还为包含双角字符的字符串生成正确的输出:

str_list = ("au200bu200b", "b", "㓵", "longest entryu200b")

|a​​            | width: 1, error: 2
|b            | width: 1, error: 0
|㓵           | width: 2, error: -1
|longest entry​| width: 13, error: 1

最新更新