如何让Expect仅匹配最后一条send语句对应的输出?
解决Expect匹配旧输出的问题
问题出在Expect的输入缓冲区机制:它会从缓冲区头部开始匹配正则表达式,之前的expect *没有彻底消费完前面命令的输出,导致缓冲区里残留了符合最后一次匹配规则的内容,被优先命中。
用下面两种方法解决:
方法一:精准匹配命令结束标记(推荐)
找到gpshell执行完每条命令后输出的固定标识(比如提示符、成功提示),替换掉模糊的expect *,确保每条命令的输出都被完全消费。比如假设gpshell执行完命令后会输出OK并回到gpshell>提示符,修改后的脚本如下:
#!/usr/bin/env expect -f log_user 0 exp_internal 1 spawn gpshell # 匹配启动后的初始提示符 expect -re {gpshell>} send "establish_context\r" # 匹配命令执行成功+提示符,确保输出全被消费 expect -re {OK.*gpshell>} send "enable_trace\r" expect -re {OK.*gpshell>} send "card_connect\r" expect -re {OK.*gpshell>} send "send_apdu -sc 0 -APDU 00a40004023f00\r" expect -re {OK.*gpshell>} send "send_apdu -sc 0 -APDU 00a40804022fe2\r" expect -re {OK.*gpshell>} # 执行最后一条命令 send "send_apdu -sc 0 -APDU 00B000000A\r" # 此时缓冲区只有这条命令的输出,匹配不会出错 expect -indices -re {(?n)<-- ([0-9]+).*$} set iccid $expect_out(1,string) puts $iccid send "card_disconnect\r" expect -re {OK.*gpshell>} send "release_context\r" expect -re {OK.*gpshell>} send \x03 exit 0
方法二:清空缓冲区后执行最后一条命令
如果找不到明确的结束标记,就在最后一次send前,用短超时消费掉缓冲区所有剩余内容,确保后续匹配只针对最后一条命令的输出:
#!/usr/bin/env expect -f log_user 0 exp_internal 1 spawn gpshell expect * send "establish_context\r" expect * send "enable_trace\r" expect * send "card_connect\r" expect * send "send_apdu -sc 0 -APDU 00a40004023f00\r" expect * send "send_apdu -sc 0 -APDU 00a40804022fe2\r" # 设置0.5秒短超时,消费缓冲区所有现有输出 expect -timeout 0.5 -re .* # 执行最后一条命令 send "send_apdu -sc 0 -APDU 00B000000A\r" expect -indices -re {(?n)<-- ([0-9]+).*$} set iccid $expect_out(1,string) puts $iccid send "card_disconnect\r" send "release_context\r" send \x03 exit 0
补充说明:原来的expect *是模糊匹配,可能只消费了部分输出,残留内容留在缓冲区里。用expect -re .*配合短超时,可以尽可能清空缓冲区,避免旧内容干扰后续匹配。
内容的提问来源于stack exchange,提问作者k_o_
相关产品推荐
相关产品推荐

