You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:10:49