Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
506 views
in Technique[技术] by (71.8m points)

tcl - how to clean up the previous expect_buf in an expect script

I've written a expect function to get the output of a command and my code is like below

proc do_cmd {cmd id} {
  set spawn_id $id
  send "$cmd
"
  expect "$cmd
"
  expect {
    -re "
(.*)
" {return $expect_out(1,string)}
    default {exit 1}
  }
}

If I call the function just once it would works fine and return something I want, but if I call it continually without a break, it would return something unwanted.

# 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

I use the 'exp_internal 1' to debug it and found that the expect_out in the second called command still holds the previous output info and caused the matched problem, so how can I clean up the expect_out buffer(I tried to set it an empty string but it doesn't work,) or is there anything else I can do to avoid this problem? Thanks in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Don Libes's suggestion for your scenario is as follows,

Sometimes it is even useful to say:

expect *

Here the * matches anything. This is like saying, "I don't care what's in the input buffer. Throw it away." This pattern always matches, even if nothing is there. Remember that * matches anything, and the empty string is anything! As a corollary of this behavior, this command always returns immediately. It never waits for new data to arrive. It does not have to since it matches everything.

Reference : Exploring Expect

In this case, after your required match, better try to save the match to some variable then simply add the code expect * at the last. This will empty the buffer. Your code can altered as below.

proc do_cmd {cmd id} {
  set spawn_id $id
  send "$cmd
"
  #Looks like you are looking for a particular command to arrive
  expect "$cmd
"
  #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 "
(.*)
" {set result $expect_out(1,string)}}
    }
  #Causing the buffer to clear and it will return quickly
  expect *
  return $result
}

Apart from this, there is one more way can be unsetting the expect_out(buffer) content itself which will remove the 'buffer' index from expect_out array which can be depicted as

unset expect_out(buffer)

When the next match happens, expect_out array will be updated the index 'buffer' and we can have the fresh expect_out(buffer) value. Replace the expect * with the above code if you prefer to use this way.

This is quite a workaround kind of stuff to get what we want actually. You can go ahead with any approach. Choice is yours. :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...