【问题标题】:Filter special chars such as color codes from shell output从 shell 输出中过滤特殊字符,例如颜色代码
【发布时间】:2015-05-24 15:18:21
【问题描述】:

我在 python 中运行 shell 命令,将它们的输出记录到文件中,最后显示在网页上。然而,命令输出的颜色样式字符也被记录下来。有没有办法过滤掉颜色样式字符或在网页上正确显示它们?非常感谢!

输出日志:

" 22200K .......\u001b[0m\u001b[91m... .......... ...\u001b[0m\u001b[91m.\u001b[0m\u001b[91m...... .........\u001b[0m\u001b[91m.\u001b[0m\u001b[91m \u001b[0m\u001b[91m.\u001b[0m\u001b[91m.\u001b[0m\u001b[91m.\u001b[0m\u001b[91m.\u001b[0m\u001b[91m...... 50% 28.6K 12m55s"

真正的文字:

[INFO][88] 22250K .......... .......... .......... .......... .......... 50% 35.8K 12m53s

【问题讨论】:

标签: python shell


【解决方案1】:

在不太可能的情况下,如果您也有 xterm256 颜色代码,这将过滤“正常”ansi 和 xterm256 ansi 代码:

import re
print re.sub(r'\x1b(\[.*?[@-~]|\].*?(\x07|\x1b\\))', '', a)

或以稍微不那么模糊且更易读的形式:

'(' + CSI + '.*?' + CMD + '|' + OSC + '.*?' + '(' + ST + '|' + BEL + ')' + ')'

带有测试的完整代码:

import re

tests = [
    u"22200K .......\u001b[0m\u001b[91m... .......... ...\u001b[0m\u001b[91m.\u001b[0m\u001b[91m...... .........\u001b[0m\u001b[91m.\u001b[0m\u001b[91m \u001b[0m\u001b[91m.\u001b[0m\u001b[91m.\u001b[0m\u001b[91m.\u001b[0m\u001b[91m.\u001b[0m\u001b[91m...... 50% 28.6K 12m55s",
    u"=\u001b[m=",
    u"-\u001b]23\u0007-",
]

def trim_ansi(a):
    ESC = r'\x1b'
    CSI = ESC + r'\['
    OSC = ESC + r'\]'
    CMD = '[@-~]'
    ST = ESC + r'\\'
    BEL = r'\x07'
    pattern = '(' + CSI + '.*?' + CMD + '|' + OSC + '.*?' + '(' + ST + '|' + BEL + ')' + ')'
    return re.sub(pattern, '', a)

for t in tests:
    print trim_ansi(t)

【讨论】:

    【解决方案2】:

    这应该适用于大多数情况:

    import re
    print re.sub(u'\u001b\[.*?[@-~]', '', a)
    

    更新

    转义序列以字符 ESC 开头(ASCII 十进制 27/十六进制 0x1B/八进制 033)。对于两个字符序列,第二个字符在 ASCII 64–95 范围内(@ 到 _)。 但是,大多数序列多于两个字符,并且以字符 ESC 和 [(左括号)开头。该序列称为控制序列引入器(或控制序列发起器)的 CSI。这些序列的最后一个字符在 ASCII 64–126 范围内(@ 到 ~)。 (http://en.wikipedia.org/wiki/ANSI_escape_code)

    更新2

    使用以下“a.py”:

    import sys, re
    
    for line in sys.stdin:
        sys.stdout.write(re.sub(u'\u001b\[.*?[@-~]', '', line))
    

    这对我来说很顺利:

    ls --color | python a.py
    

    【讨论】:

    • 谢谢,杰蒂科!实际上,我希望所有彩色外壳输出的通用方式。我在问题中描述的示例只是其中之一。
    • 这是一种快速且完全不是通用的解决方案,但它应该涵盖实践中使用的大多数 ANSI 代码。举一个这个块没有过滤的代码的例子,我也会整合它们。或者使用@jonrsharpe 建议的完整解决方案
    • 你能举个例子说明它对你不起作用吗?在 Update2 中,我举例说明了它是如何为我工作的。
    • 在更新 #2 的 python 脚本中再次尝试。现在为我工作!非常感谢!我将尝试使用其他更复杂的案例。顺便说一句,这段代码 re.sub('r'\x1b([.*?[@-~]|].*?(\x07|\x1b\))', '', a) 有错字。 'r' 中有多余的单引号
    • 已修复,谢谢。您也可以尝试我的第三个答案中链接的食谱,但它可能对您不起作用,因为它只处理“正常”的 ansi 代码。
    【解决方案3】:

    【讨论】:

      【解决方案4】:

      您可以简单地通过strings 管道输出以删除任何不可打印的字符:

      ./some-script | strings
      

      【讨论】:

      • 这不起作用:ls --color |strings 保留所有颜色代码,只省略其中的第一个 ESC 符号。
      猜你喜欢
      • 2011-02-11
      • 1970-01-01
      • 2023-03-07
      • 2013-01-29
      • 1970-01-01
      • 2015-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多