Python 计算字符串格式宽度字段中的零长度控制字符?

Python counting zero-length control characters in string formatting width field?

在 Python 3.4.3 中,我尝试使用 string.format() 运算符对某些字段进行宽度对齐,它似乎将零长度控制字符计入总宽度。示例代码:

ANSI_RED = "3[31m"
ANSI_DEFAULT="3[39m3[49m"

string1 = "12"
string2 = ANSI_RED+"12"+ANSI_DEFAULT

print("foo{:4s}bar".format(string1))
print("foo{:4s}bar".format(string2))

这将输出:

foo12  bar
foo12bar

(第二个输出的“12”为红色,但我无法在 SO 中重现)

在第二种情况下,我丢失了字段宽度,我假设是因为 Python 看到字符串中的字符总数大于宽度,尽管这些字符中的大部分结果为零- 在符合 ANSI 标准的终端上的长度。

使用 ANSI 颜色和工作域宽度的简洁方法是什么?

What's a clean way of having ANSI colors and working field widths?

不幸的是,您将不得不去除转义序列以获得显示的字段宽度。

len() 函数 returns Python 2 str 类型中的字节数和 Python 3 str 类型中的代码点数。该长度从未保证与显示宽度匹配(这是一个更具挑战性的问题):

>>> s = 'abc\bde'
>>> print s
abcde
>>> len(s)
6

一般来说,除非您了解显示器将如何解释代码(即宽度因设备是否支持 ANSI 转义序列而异),否则您无法确定显示宽度。

我不知道它是否符合 "clean" 但以下内容是可行的:

print("foo{0}{1:4s}{2}bar".format(ANSI_RED, string1, ANSI_DEFAULT))

正确设置终端控制代码非常困难(如下所示,并非所有代码都有明确定义的宽度),因此最好的选择可能是使用显式列移动。

# string2 defined as above
def col(n): return "3[{:d}G".format(n)
print("foo{:s}{:s}bar".format(string2,col(8)))

输出:

foo12  bar