Expect is very powerful, but often difficult to get right (at least for me).  One thing that helps to debug is to print a lot of output.  I also find myself referring to the man page for Perl/Expect:  man Expect, which is a partial answer to your first question.

One trick I've recently started using is to send a unique pattern to the remote host, expect that pattern back, and then just parse all of the text surrounding it.

Here's an example:

use strict; use warnings; ############# ## Globals ## ############# my $sendex_index = 0; ################# ## Subroutines ## ################# # # sendex # # Inputs: $1 - the Expect object # $2 - (optional) a verbosity level, if greater than 1, # displays verbose results in the send_expect() subrou +tine. # $3 - (optional) a timeout in seconds # $4 - (optional) a command to send to the remote host # # Results: Sends the command (if any) to the remote host, and then # tries to send a unique string of the format "Okay<number> +.", # where <number> will start with '1', and increase on each +call # to this subroutine. # # Returned will be the same info hash as returned by the # call send_expect(). # sub sendex { my ($exp, $vflag, $timeout, $cmd) = @_; $timeout ||= 3; ++$sendex_index; ($cmd || "") and $exp->send("$cmd\n"); my $okay = "echo -n Okay; echo -n $sendex_index; echo '.'"; my $pat = "Okay${sendex_index}."; $vflag ||= 0; return send_expect($exp, $timeout, $okay, $pat, $vflag); } # # send_expect # # Inputs: $1 - the Expect object # $2 - a timeout in seconds # $3 - a command to send to the remote host # $4 - the expected pattern to match # $5 - (optional) a verbosity level, if greater than 1, # displays verbose results # # Results: Sends the command (if any), and attempts to send a unique # string of the format "Okay<number>.", where <number> will # start with '1', and increase on each call. # # Returned will be the same info hash as returned by the # call send_expect(). # sub send_expect { my ($exp, $timeout, $cmd, $pat, $vflag) = @_; $vflag ||= 0; if ($vflag > 1) { print "=" x 79, "\n"; print "Sending text .... '$cmd'\n"; } $exp->send("$cmd\n"); if ($vflag > 1) { print "Expected text ... '$pat'\n"; } my $origstr = $pat; my $b_regex = ($pat =~ s,^/(.+)/$,$1,)? 1: 0; my @expargs = $b_regex? (-re, $pat): ($pat); my $result = $exp->expect($timeout, @expargs); $result or die "sent '$cmd', did not get '$origstr'\n"; my $before = $exp->before; my $match = $exp->match; my $after = $exp->after; my $c_strip = sub { my ($s_str) = @_; $$s_str =~ s/\e\]0;//g; $$s_str =~ s/\e\[[^m]*m//g; }; $c_strip->(\$before); $c_strip->(\$match); $c_strip->(\$after); if ($vflag > 1) { print "Full response:\n"; print "${before}${match}${after}\n"; print "=" x 79, "\n\n"; } return { 'before' => $before, 'match' => $match, 'after' => $after + }; }

Each time you call sendex(), it echos a different pattern on the remote host (although it does so by echoing pieces of the pattern, so that the call to expect() doesn't succeed too early!):

Okay1 Okay2 Okay3 ...

and as soon as it receives the expected pattern, it sends back a hash containing the 'before', 'match', and 'after' patterns, which you can then parse to suit your needs.


s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/

In reply to Re: Expect.pm question by liverpole
in thread Expect.pm question by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.