忽略预期响应中的ANSI颜色

问题描述 投票:1回答:2

我可以使用pexpect来忽略输出中的ANSI转义码(尤其是颜色)吗?我正在尝试这样做:

expect('foo 3 bar 5')

...但是有时我得到带有ANSI彩色数字的输出。问题是我不知道哪个数字将具有ANSI颜色,而哪些则没有。

是否有使用pexpect的方法,但是在子进程的响应中是否忽略了ANSI序列?

pexpect ansi-escape
2个回答
0
投票

此替代方法部分地违反了使用pexpect的目的,但它满足了我的要求。

想法是:

  1. [expect的所有内容(正则表达式匹配.*),然后是下一个提示(在我的情况下是xsh $-注意“提示”正则表达式中的反斜杠)]
  2. 获取after属性
  3. 删除提示:[1:]
  4. 从中删除ANSI转义码
  5. 将过滤后的文本与我的“预期”响应正则表达式进行比较
with pexpect.spawn(XINU_CMD, timeout=3, encoding='utf-8') as c:
    ansi_escape = re.compile(r"\x1B[@-_][0-?]*[ -/]*[@-~]")
    system_prompt_wildcard = r".*xsh \$ "  # backslash because prompt is "xsh $ "

    # tests is {command:str, responses:[str]}
    for test in tests:
        c.sendline(test["cmd"])
        response = c.expect([system_prompt_wildcard, pexpect.EOF, pexpect.TIMEOUT]) #=> (0|1|2)

        if response != 0: # any error
            continue

        response_text = c.after.split('\n')[1:]
        for expected, actual in zip(test['responses'], response_text):
            norm_a = ansi_escape.sub('', norm_input.sub('', actual.strip()))
            result = re.compile(norm_a).findall(expected)
            if not len(result):
                print('NO MATCH FOUND')

0
投票

这是一个不完全令人满意的建议,将pexpect类的两个例程pexpect.Expecterpexpect.spawn子类化,以便传入的数据可以在将其添加到缓冲区并测试模式匹配之前删除转义序列。这是一个懒惰的实现,因为它假定将始终以原子方式读取任何转义序列,但是应对拆分读取则更加困难。

import re, pexpect
from pexpect.expect import searcher_re

# regex for vt100 from https://stackoverflow.com/a/14693789/5008284  
class MyExpecter(pexpect.Expecter):
    ansi_escape = re.compile(rb'\x1B[@-_][0-?]*[ -/]*[@-~]')

    def new_data(self, data):
        data = self.ansi_escape.sub(b'', data)
        return pexpect.Expecter.new_data(self, data)

class Myspawn(pexpect.spawn):
    def expect_list(self, pattern_list, timeout=-1, searchwindowsize=-1,
                    async=False):
        if timeout == -1:
            timeout = self.timeout
        exp = MyExpecter(self, searcher_re(pattern_list), searchwindowsize)
        return exp.expect_loop(timeout)

这假定您将expect()调用与列表一起使用,然后执行

child = Myspawn("...")
rc = child.expect(['pat1'])

由于某些原因,在解码数据之前,我不得不使用字节而不是字符串,但这可能是由于当前不正确的语言环境造成的。

© www.soinside.com 2019 - 2024. All rights reserved.