| |||||||||||
Expect - Simultaneous pattern matching Posted by neilvp (neilvp), 5 September 2006 I am attempting to match a number of possible patterns that are being sent in a text file to Stdin using cat.According to the section 'Pattern-Action Pairs' in "Exploring Expect" Pg 75/76 I can set up while {1} { expect \ { "hi" {Send_Output "HI\r" } "hello" {Send_Output "HELLO\r"} "bye" {Send_Output "BYE\r"} timeout {Time_Out; break} eof {puts "\rBreaking - EOF\r" ; break} } } and Expect will simultaneously look for "hi", "hello" and "bye" and take the appropriate action if matched. So if I send a text file that is hello hi bonjour bye I would expect (pun intended) to see on Send_Output HELLO HI BYE Is my expectation correct? Because what I get is HI BYE The full code and test file are attached. Would you please try this on unix and see what happens and if possible explain what is going on and why it is I do not see what I expect to see. Many thanks Neil The Code ******************** #!/bin/sh # The line above enables this script to work on both Unix and Windows. (Yeah right) ## ****************************************************************************** ## ## TCL script to test simultaneous Expect statement. ## " Exploring Expect" Pg 76 ## ## 31 Aug 06 ## Neil Peers ## ## Description ## ## ## ***************************************************************************** package require Expect puts "\n\n*******************************************" puts "Run starting at [clock format [clock seconds] -gmt true -format "%d %b %Y %r %Z"]" puts "*******************************************\n\n" set loop 0 # loop is used as an indicator in the output file as to how many # times the Send_Output routine is called. set FileToRead hi_test.txt set TestOutputFile hi_results.txt set fileID [open $TestOutputFile w] # $TestOutputFile is the file the script will write to. # Open and close it to make sure a) it exists and b) it is clear. close $fileID # Send_Output opens the output file, writes the inbound string # to it and then closes the file again. proc Send_Output {sendstring} \ { global TestOutputFile global loop incr loop set fileID [open $TestOutputFile a] puts $fileID "$loop $sendstring" close $fileID } if { [catch {open $TestOutputFile w} fileID] }\ { puts "Cannot open $TestOutputFile" } else \ { puts "file $TestOutputFile is open\r" close $fileID puts "closed it\r" } if [catch {spawn cat $FileToRead} reason]\ { puts "Failed to spawn\r" puts "Reason $reason\r" } else { puts "spawned" } while {1} \ { expect \ { "hi" {Send_Output "HI\r" } "hello" {Send_Output "HELLO\r"} "bye" {Send_Output "BYE\r"} timeout {Time_Out; break} eof {puts "\rBreaking - EOF\r" ; break} } } puts "Ending Program" ************************************** ************************************** Test file hello hi bonjour bye Posted by admin (Graham Ellis), 6 September 2006 Your script is checking for each of the possible strings <i>in the order in which they occur in the multiple choice expect statement</i>; I reproduced your reported behavioud then switched towhile {1} \ { expect \ { "hello" {Send_Output "HELLO\r"} "hi" {Send_Output "HI\r" } "bye" {Send_Output "BYE\r"} timeout {Time_Out; break} eof {puts "\rBreaking - EOF\r" ; break} } } which gave me 1 HELLO 2 HI 3 BYE longer explanation ... Your spawned cat command starts pouring text into a bucket as soon as it's started, then (when it gets a look in on the c.p.u.) the expect command asks .... 1. Do I have a hi? and it doesn't get any further because, yes, as the time both the hello and the hi have been added to the bucket, so it returns. Then the expect command carries on and asks 1. Do I have a hi? 2. Do I have a hello? 3. Do I have a bye? And it gets a match in that last case, so it returns because of the bye Finally (third loop) the first thing that matches is the eof. The problem that you are reporting (in essence) is that you're hoping to look for whichever of the incoming strings occurs first in the stream of data that cat's producing, rather than asking for each in turn, and that's going to give you different results if the buffer (bucket) contains several matches when you get round to checking it. Ironically, your program would probably have produced the results you wanted if you had not used the cat sommand but something that's much slower to send the output through, such as a 'real' program that does a lot of work before outputting each result line. But in a way, thank goodness you've raised the issue now as that would have been a program that would have sometimes failed on a busy machine or on a different o/s with a different timesharing algortithm - such are typical expect issues A solution? I'm sure that in reality, you're NOT trying to cat a file with various greetings in it, but rather to process each line of an incoming flow in different ways, with additional (fallback) traps for timeout and eof. Here's your code, modified to do that: Code:
The method is to have expect look for each new line, then to look for the appropriate pattern within each line. If a line does not match at all, it is skipped. And I've generalised the code to allow easily for more than 3 interesting inputs .... The results file I got: 1 ELLO 2 GDAY 3 TARA Very good question, Neil ... This page is a thread posted to the opentalk forum
at www.opentalk.org.uk and
archived here for reference. To jump to the archive index please
follow this link.
|
| ||||||||||
PH: 01144 1225 708225 • FAX: 01144 1225 793803 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho |