pexpect.expect('(?<=Code:\s).*(?=[\r\n])') 有时会从多行输出中得到意想不到的结果

pexpect.expect('(?<=Code:\s).*(?=[\r\n])') sometimes got unexpected result from multiline output

我是学习 python 和 pexpect 的新手,我正在尝试检查字典是否等于某些命令输出中的某个字符串,但由于某种原因,字符串比较在极少数情况下会失败但大部分时间都会过去。

假设我向我的终端发送了一些名为 list 的命令,它输出了某个产品的详细信息:

->list
Color: Maroon Red
Height: 150cm
Code: 4KG-LV
Material: Aluminum
Brand: Toyota 
#and hundreds of more lines...

我有一个代表字典的变量,当我使用 print(license_type):

打印它时输出它
{'license': '4kg-lv'}

我基本上想检查 list 命令输出的代码 4KG-LV 是否等于字典中许可证的值 4kg-lv

这样做:

exp.sendline("list")
exp.expect('(?<=Code:\s).*(?=[\r\n])')
firstString = exp.after
print(firstString) 

使用正则表达式和 gets/prints 值 4KG-LV.

解析列表命令的输出

如果我将所有这些都放在 python 脚本中并检查这两个值是否相等,它应该通过检查,因为我打印了这 2 个字符串并且它们在我的终端上看起来相同。但是,当我尝试检查第一个字符串(来自 list 命令的代码)是否等于字典值时,它会在 95% 的时间内作为 EQUAL 传递,但在极少数情况下,由于某种原因它无法比较并且我不知道为什么。

license_type = {'license': '4kg-lv'}
exp.sendline("list")
exp.expect('(?<=Code:\s).*(?=[\r\n])')
codeString = exp.after

firstString = codeString.lower().strip(' \t\n\r')
secondString = licenseType.get("type").lower().strip(' \t\n\r')

if firstString == secondString
    print("EQUAL")
else:
    print("NOT EQUAL")

我在这部分代码上面有很多命令和输出,我不确定当我 运行 脚本时它是否正在读取额外的 space 或 \n ?比较失败可能就像每 30-40 运行 秒一次。没有 .strip(' \t\n\r') 它每次都会自动失败,但添加它似乎使它在大部分时间都通过了,但我不确定是什么导致它在极少数情况下失败。

有没有可能它忽略 spaces/tabs 太迟了?我应该在 .lower() 之前添加 strip.(' \t\n\r') 吗?

看来你应该改变

exp.expect('(?<=Code:\s).*(?=[\r\n])')

exp.expect('(?<=Code:\s)[^\r\n]*(?=[\r\n])')

否则,贪心.*可能会匹配交叉换行符(取决于应用程序输出的速度和预期读取数据的速度),例如,"4KG-LV\r\nMaterial: Aluminum".


示例:

一个简单的预期脚本foo.py:

import pexpect, sys

p = pexpect.spawnu('bash -c "echo : foo; ((RANDOM % 2)) && sleep .1; echo : bar" ')
p.expect('(?<=:\s).*(?=[\r\n])')
matched = p.after
p.expect(pexpect.EOF)

print('MATCHED: %s' % repr(matched) )

试一试:

$ for i in {1..10}; do python3 foo.py; done
MATCHED: 'foo\r\n: bar\r'
MATCHED: 'foo\r'
MATCHED: 'foo\r\n: bar\r'
MATCHED: 'foo\r'
MATCHED: 'foo\r'
MATCHED: 'foo\r'
MATCHED: 'foo\r'
MATCHED: 'foo\r\n: bar\r'
MATCHED: 'foo\r\n: bar\r'
MATCHED: 'foo\r\n: bar\r'