如何在expect脚本中清理以前的expect_buf

use*_*366 6 tcl expect

我编写了一个期望函数来获取命令的输出,我的代码如下所示

proc do_cmd {cmd id} {
  set spawn_id $id
  send "$cmd\r"
  expect "$cmd\r"
  expect {
    -re "\n(.*)\r\n" {return $expect_out(1,string)}
    default {exit 1}
  }
}
Run Code Online (Sandbox Code Playgroud)

如果我只调用一次它可以正常工作并返回我想要的东西,但是如果我连续不停地调用它,它会返回不需要的东西.

# test case 1
set ret [do_cmd $mycmd $spawn_id]
puts "$mycmd returns $ret"  # the return value is ok

# test case 2
set ret [do_cmd $mycmd $spawn_id]
set ret [do_cmd $mycmd $spawn_id]
puts "$mycmd returns $ret"  # the return value is not something I want
Run Code Online (Sandbox Code Playgroud)

我使用'exp_internal 1'来调试它,发现第二个被调用命令中的expect_out仍然保存了先前的输出信息并导致匹配问题,所以如何清理expect_out缓冲区(我试图将它设置为空字符串)但它不起作用,或者还有什么我可以做的,以避免这个问题?提前致谢.

Din*_*esh 11

Don Libes对您的方案的建议如下,

有时甚至说:

expect *

这里*匹配任何东西.这就好说,"我不在乎输入缓冲区中的内容.扔掉它." 这种模式总是匹配,即使没有任何东西.请记住*匹配任何东西,空字符串是任何东西!作为此行为的必然结果,此命令始终立即返回.它永远不会等待新数据到来.它没有必要因为它匹配所有东西.

参考:探索期待

在这种情况下,在您需要的匹配之后,最好尝试将匹配保存到某个变量,然后只需expect *在最后添加代码.这将清空缓冲区.您的代码可以更改如下.

proc do_cmd {cmd id} {
  set spawn_id $id
  send "$cmd\r"
  #Looks like you are looking for a particular command to arrive
  expect "$cmd\r"
  #Then you have one more expect here which is you want to get it
  expect {
    #Saving the value sub match to the variable 'result'
    -re "\n(.*)\r\n" {set result $expect_out(1,string)}}
    }
  #Causing the buffer to clear and it will return quickly
  expect *
  return $result
}
Run Code Online (Sandbox Code Playgroud)

除此之外,还有一种方法可以取消expect_out(buffer)内容本身,这将从expect_out数组中删除"缓冲区"索引 ,可以将其描述为

unset expect_out(buffer)
Run Code Online (Sandbox Code Playgroud)

当下一个匹配发生时,expect_out数组将更新索引'缓冲区',我们可以获得新expect_out(buffer)值.expect *如果您更喜欢使用这种方式,请使用上面的代码替换.

这是一种解决方法,可以实现我们想要的东西.您可以采取任何方法.选择是你的.:)