【问题标题】:How can I parse Linux terminal colour codes?如何解析 Linux 终端颜色代码?
【发布时间】:2021-02-08 20:12:44
【问题描述】:

我正在尝试在 curses python 应用程序中显示文件中的彩色文本。该文件包含 24 位颜色转义码,例如:^[[48;2;255;255;255m^[[38;2;255;255;255mA。我需要遍历文件并生成一个元组列表,其中包含如下元组:((background: r, g, b), (foreground: r, g, b), char)。这是我到目前为止尝试过的代码。它试图找到所有 0x27 字节并解析它们,但它似乎不起作用,而且不仅不是特别安全/可扩展/可维护。如何解析这样的文件中的颜色代码?有图书馆吗?如果没有库,如何改进此代码?

def read_until(char, data, pos):
    """read from a bytes-like object starting at `pos` until the target character is found"""
    start = pos
    while data[pos] != char: pos += 1
    return data[start:pos], pos

def makeData(data):
    assert type(data) == bytes

    out = []
    pos = 0
    bg = (0, 0, 0)
    fg = (255, 255, 255)

    while pos < len(data):
        if data[pos] == 27: #start of the escape sequence
            pos += 2 #+2 to ignore the `[` char
            if data[pos:pos + 2] == b"0m": #reset character, just ignore it
                continue
            first_num, pos = read_until(ord(";"), data, pos)
            second_num, pos = read_until(ord(";"), data, pos + 1) #+ 1 for the `;` char

            r, pos = read_until(ord(";"), data, pos + 1)
            g, pos = read_until(ord(";"), data, pos + 1)
            b, pos = read_until(ord("m"), data, pos + 1)
            r = int(r)
            g = int(g)
            b = int(b)
            pos += 1 #skip last `m` char
            if first_num == b"48": #48 means foreground
                fg = (r, g, b)
            elif first_num == b"38": #38 means background
                bg = (r, g, b)
        else:
            out.append((fg, bg, chr(data[pos]))) #use current fg and bg colours with char
            pos += 1
    return out

with open("file.txt", "rb") as f:
    print("".join([chr(i[2]) for i in makeData(f.read())])) #print without colour codes, to test

【问题讨论】:

    标签: python linux terminal


    【解决方案1】:

    您可以使用正则表达式来解析数据:

    import re
    with open("file.txt") as f:
        result = re.findall(r'\x1b\[48;2;(\d+);(\d+);(\d+)m\x1b\[38;2;(\d+);(\d+);(\d+)m(.)', f.read())
        print(result)
    

    【讨论】:

    • 这是一个好的开始,但它不能区分背景颜色和前景,而且我还需要实际的字符。使用正则表达式这一切都可能吗?
    • char 是什么?是A 吗? 48代表前景吗?
    • 是的,A是char,48&38代表前景和背景
    • 完美!谢谢!
    猜你喜欢
    • 2013-12-21
    • 2011-03-31
    • 2019-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-01
    • 2021-10-23
    • 2017-04-06
    相关资源
    最近更新 更多