|
|
 |
 |
 |
 |
TCL(Tool Command Language) Scripting
|
 |
 |
 |
 |
 |
 |
 |
 |
Strange behavior when I tried to use expect -re {.*} to get the whole output from a command.
Hi all, In my expect script, I tried to use: expect -re {.*} ... to get all the output of a command, but it didn't. The following is the command I send: insert into table1 values (1,'abcde');commit; and the output is like: SQL> insert into table1 values (1, 'abcde'); Transaction Done SQL> In my script, there's a place expecting the prompt "SQL>". But because it appears in the output more than once, I have to use "expect -re {.*}" to get the rest of the output. The problem is that it doesn't seem to work. My script is like: expect { -re $lTargetPrompt { append lOutput $expect_out(buffer) expect -re {.*} {append lOutput $expect_out(buffer)} } ... }
Does anyone have any ideas? Thanks in advance! Jack
On May 10, 6:03 am, zhjac@gmail.com wrote:
> Hi all, > In my expect script, I tried to use: > expect -re {.*} ... > to get all the output of a command, but it didn't. > The following is the command I send: > insert into table1 values (1,'abcde');commit; > and the output is like: > SQL> insert into table1 values (1, 'abcde'); > Transaction Done > SQL> > In my script, there's a place expecting the prompt "SQL>". But because > it appears in the output more than once, I have to use "expect -re > {.*}" to get the rest of the output. The problem is that it doesn't > seem to work. > My script is like: > expect { > -re $lTargetPrompt { > append lOutput $expect_out(buffer) > expect -re {.*} {append lOutput $expect_out(buffer)} > } > ... > } > Does anyone have any ideas? > Thanks in advance! > Jack
yes, the regexp {.*} matches 0 or more so it wont even look at the expect buffer it just matches on "" Also since you don't know what the expect buffer has at one time if you dont provide anything to anchor your regexp you can get different results every time you run your program especially if you provide a catch all that absorbs the expect_out(buffer) every time through the loop. For instance ( see code below) because of system load the initial expect buffer is "xxxxxSQL>" then it will match and everything is fine and it never reaches the catch all. Under heavy load the buffer may only be "xxxxxSQ" your catch all will match and on the next go round the "QL>" will not match either resulting in the catch all running expect { -re {(.*)SQL>} { append output $expect_out(1,string)\n" puts "FOUND MATCH $output" } -re {.+} { append output $expect_out(buffer); puts "CATCHALL" since your expression SQL> is never seen then it never matches. A better way is to do this: expect { -re {(.*)SQL>$} { # prompt are usually on line by itself append output $expect_out(1,string) incr count if { $count < $expectedNumPrompts } { exp_continue; } } -re {^.*$} { # match lines lappend output $expect_out(buffer) } eof { ; } timeout { exp_continue ; } } Carl
On May 10, 9:39 am, Bezoar <cwjo@gmail.com> wrote:
> On May 10, 6:03 am, zhjac @gmail.com wrote: > > Hi all, > > In my expect script, I tried to use: > > expect -re {.*} ... > > to get all the output of a command, but it didn't. > > The following is the command I send: > > insert into table1 values (1,'abcde');commit; > > and the output is like: > > SQL> insert into table1 values (1, 'abcde'); > > Transaction Done > > SQL> > > In my script, there's a place expecting the prompt "SQL>". But because > > it appears in the output more than once, I have to use "expect -re > > {.*}" to get the rest of the output. The problem is that it doesn't > > seem to work. > > My script is like: > > expect { > > -re $lTargetPrompt { > > append lOutput $expect_out(buffer) > > expect -re {.*} {append lOutput $expect_out(buffer)} > > } > > ... > > } > > Does anyone have any ideas? > > Thanks in advance! > > Jack > yes, the regexp {.*} matches 0 or more so it wont even look at the > expect buffer it just matches on "" > Also since you don't know what the expect buffer has at one time if > you dont provide anything to anchor > your regexp you can get different results every time you run your > program especially if you provide a > catch all that absorbs the expect_out(buffer) every time through the > loop. For instance ( see code below) > because of system load the initial expect buffer is "xxxxxSQL>" then > it will match and everything is fine and it never > reaches the catch all. Under heavy load the buffer may only be > "xxxxxSQ" your catch all will match and > on the next go round the "QL>" will not match either resulting in the > catch all running > expect { > -re {(.*)SQL>} { > append output $expect_out(1,string)\n" > puts "FOUND MATCH $output" > } > -re {.+} { > append output $expect_out(buffer); > puts "CATCHALL" > since your expression SQL> is never seen then it never matches. A > better way is to do this: > expect { > -re {(.*)SQL>$} { # prompt are usually on line by itself > append output $expect_out(1,string) incr count > if { $count < $expectedNumPrompts } { > exp_continue; > } > } > -re {^.*$} { # match lines > lappend output $expect_out(buffer) > } > eof { > ; > } > timeout { > exp_continue ; > } > } > Carl
Sorry post was incorrect Google posted it before I could finish editing it Correction below: yes, the regexp {.*} matches 0 or more so it wont even look at the expect buffer it just matches on "" Also since you don't know what the expect buffer has at one time if you dont provide anything to anchor your regexp you can get different results every time you run your program especially if you provide a catch all that absorbs the expect_out(buffer) every time through the loop. For instance ( see code below) because of system load the initial expect buffer is "xxxxxSQL>" then it will match and everything is fine and it never reaches the catch all. Under heavy load the buffer may only be "xxxxxSQ" your catch all will match and on the next go round the "QL>" will not match either resulting in the catch all running expect { -re {(.*)SQL>} { append output "$expect_out(1,string)\n" send_user "FOUND MATCH $output\r" } -re {.+} { append output $expect_out(buffer); send_user "CATCHALL\n" exp_continue; } } results in first case: FOUND MATCH ... in second case CATCHALL CATCHALL A better way is to do this: #!/opt/usr/bin/tclsh8.5 package require Expect spawn <program> expect -re {.*SQL>} { send "<command>\r" }
set output "" exp_internal 0; # set to 1 for deep debugging log_user 0 ; # set to 1 to see the program output set count 0; # keep count of prompts set expectedNumPrompts 1 ; # num prompts we want to see # if we dont know the number prompts than another anchor #(match expression) must be used or timeout/eof expect { -re {(.*)SQL>} { append output $expect_out(1,string) send_user "." incr count if { $count < $expectedNumPrompts } { exp_continue; } } eof { send_user"+"; } timeout { exp_continue ; } }
puts "$output" Carl
In article <1178795034.155683.94@e65g2000hsc.googlegroups.com>,
<zhjac @gmail.com> wrote: >Hi all, >In my expect script, I tried to use: >expect -re {.*} ... >to get all the output of a command, but it didn't. >The following is the command I send: >insert into table1 values (1,'abcde');commit; >and the output is like: >SQL> insert into table1 values (1, 'abcde'); >Transaction Done >SQL> >In my script, there's a place expecting the prompt "SQL>". But because >it appears in the output more than once, I have to use "expect -re >{.*}" to get the rest of the output. The problem is that it doesn't >seem to work. >My script is like: >expect { > -re $lTargetPrompt { > append lOutput $expect_out(buffer) > expect -re {.*} {append lOutput $expect_out(buffer)} > } > ... >} >Does anyone have any ideas?
. . . There are several difficulties in the fragments you provide. I think <URL: http://wiki.tcl.tk/2958 >, <URL: http://wiki.tcl.tk/3173 >, and <URL: http://wiki.tcl.tk/18013 > will interest you. I don't understand your description. You write ... and the output is like: SQL> insert into table1 values (1, 'abcde'); Transaction Done SQL> In my script, there's a place expecting the prompt "SQL>". But because it appears in the output more than once, I have to use "expect -re {.*}" to get the rest of the output. The problem is that it doesn't ... What I see is that, after the single command "insert into ...", there's a single "SQL> " (that space might eventually be crucial, by the way) prompt. Are you saying that you're using Expect to script the launch of an existing SQL script? I suspect an experienced Expect programmer can solve your symptom in seconds. I write this to encourage you; it's very likely a solution is near at hand.
I don't know in what kind of database environment you are trying to execute your insert statement and why you use Expect. You will have valid reasons for that, so only just to be sure: You do realize that there are Tcl packages for accessing databases in a more direct way? E.g. Oratcl (http://wiki.tcl.tk/204) allows you to open a connection to an Oracle instance and execute queries like in your example without the need to use Expect (and there's no hassling with the SQL> prompt) Similar solutions exists for other databases as well (http://wiki.tcl.tk/620) Harm <zhjac @gmail.com> wrote in message news:1178795034.155683.94330@e65g2000hsc.googlegroups.com...
> Hi all, > In my expect script, I tried to use: > expect -re {.*} ... > to get all the output of a command, but it didn't. > The following is the command I send: > insert into table1 values (1,'abcde');commit; > and the output is like: > SQL> insert into table1 values (1, 'abcde'); > Transaction Done > SQL> > In my script, there's a place expecting the prompt "SQL>". But because > it appears in the output more than once, I have to use "expect -re > {.*}" to get the rest of the output. The problem is that it doesn't > seem to work. > My script is like: > expect { > -re $lTargetPrompt { > append lOutput $expect_out(buffer) > expect -re {.*} {append lOutput $expect_out(buffer)} > } > ... > } > Does anyone have any ideas? > Thanks in advance! > Jack
Hi Carl, Thanks for your answer. But my problem is that I don't know how many times the SQL> prompt will appear. That is because I'm providing some Expect API to the end users, and the command is sent by the them. What I want to do is just to collect all output from the command to a variable. I know that I can play a trick by setting a smaller timeout value and a "gotprompt" flag, but I think it is ugly. Jack
In article <1178854069.684014.77@o5g2000hsb.googlegroups.com>, <zhjac @gmail.com> wrote: >Hi Carl, >Thanks for your answer. But my problem is that I don't know how many >times the SQL> prompt will appear. That is because I'm providing some >Expect API to the end users, and the command is sent by the them. >What I want to do is just to collect all output from the command to a >variable. >I know that I can play a trick by setting a smaller timeout value and >a "gotprompt" flag, but I think it is ugly. >Jack
There *must* be a better way. What you describe sounds not only ugly, but low in reliability. It sounds as though the goal is to receive the results of SQL queries. There are *lots* of ways to do that, few of which involve guessing timeouts. Is there a way to focus your users' attention on the queries rather than "some Expect API"? It sure seems to me that would lead to more satisfaction.
|
 |
 |
 |
 |
|