我可以使用pexpect
来忽略输出中的ANSI转义码(尤其是颜色)吗?我正在尝试这样做:
expect('foo 3 bar 5')
...但是有时我得到带有ANSI彩色数字的输出。问题是我不知道哪个数字将具有ANSI颜色,而哪些则没有。
是否有使用pexpect
的方法,但是在子进程的响应中是否忽略了ANSI序列?
此替代方法部分地违反了使用pexpect
的目的,但它满足了我的要求。
想法是:
expect
的所有内容(正则表达式匹配.*
),然后是下一个提示(在我的情况下是xsh $
-注意“提示”正则表达式中的反斜杠)]after
属性[1:]
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')
这是一个不完全令人满意的建议,将pexpect类的两个例程pexpect.Expecter
和pexpect.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'])
由于某些原因,在解码数据之前,我不得不使用字节而不是字符串,但这可能是由于当前不正确的语言环境造成的。