How to access the result of a remote command in Expect

For convenience, I'll define the prompt and command first:

   set command date      ;# our remote command
   set prompt  "% "      ;# our shell or whatever prompt we have

Now we can do useful things:

   expect $prompt        ;# wait for prompt
   send   $command\r     ;# send command
   expect $command\r\n   ;# discard command echo

Finally, match and save the result and discard the next prompt:

   expect -re (.*)\r\n$prompt\r\n

Now the result is in $expect_out(1,string).

If you want to read more about this, start on page 113 of BOOK Exploring Expect. This idiom is difficult for some programmers. The point is that Expect never gives direct access to "the result of a (foreign) command"; it simply transacts send-expect dialogues, and the developer has to know how to subtract out prompts, newlines, and other conventional decorations.

PS: If the result might be more than 2000 characters, you'll need to use the match_max command to increase the buffer space.

Ken Jones: I corrected the second expect command in the example above. It originally read:

   expect $prompt\r\n    ;# discard command echo

but as the comment indicated, the intent was really to discard the command echo, which is achieved by:

   expect $command\r\n   ;# discard command echo

"Remote input-output with Expect" gives a model for line-oriented result access.

The example above didn't work for me (yes, I know that the above is not a complete programme). The following is an example which works on my FreeBSD 4.7 machine.

   set prompt ">>> "   ;# our shell or whatever prompt we have
   set command "date"  ;# the command whose output we want to catch

   spawn bash          ;# spawn the bash 

   expect "$prompt"    ;# wait for prompt

   send   "$command\r" ;# send command
   expect "$command\r" ;# discard command echo

   expect -re "(.*)\r" ;# match and save the result

The above is really an attempt to access local command output, not remote, and it will only get one line of the output (up to the first line termination). Use exp_continue to maintain the expect loop.
If you are spawning a single shell command on your own host, just spawn the command - this allows an expect 'eof' branch to trigger when the command output is complete. This also avoids match_max hassles (assuming you are matching on non-binary output.)

    spawn $command
    set lineterminationChar "\r"
    expect   {
             $lineterminationChar   { append output $expect_out(buffer);exp_continue}      
             eof                    { append output $expect_out(buffer)}
    puts $output  ;#RJ

Tip for determining your host's line terminator - put "exp_internal 1" before the "expect" command.

LV 2007 Aug 13 I suspect that the original page creator's idea of remote is "code external to the currently running tcl script or interpreter" . Otherwise, there would be some sort of rsh/telnet/rlogin/ssh type invocation.

Get in the habit of using exp_send instead of send when using Expect. If you later decide to add Tk to your script you will not collide with Tk's send command.

"How Expect can capture the exit code from a remote command"

"Remote input-output with Expect"

Category Expect