Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Expect.pm Help

by PrimeLord (Pilgrim)
on Aug 08, 2002 at 19:49 UTC ( [id://188721] : perlquestion . print w/replies, xml ) Need Help??

PrimeLord has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to learn how to use Expect in my perl scripts and I am doing a very poor job of it so far. I am hoping I can get some help from the monks. I have written two very basic programs just to see if I can figure out how this works and I guess I am just not getting it.

Here is the first program Expect_Test

use strict; use Expect; my $expect = Expect->spawn("/usr/foo/namer") or die "$!\n"; print $expect "PrimeLord\n"; my $result = $expect->expect(15,"name:") or die "Didn't get what I was + looking for:\n";
Like I said a very simple script that just calls another script namer. Here are the contents of the namer script.

use strict; use Expect; print "What is your name: "; chomp (my $name = <STDIN>); if ($name =~ /primelord/i) { print "Hello PrimeLord!\n"; } else { print "Hello $name! I don't know you!\n"; }
So I would expect when I run Expect_Test for it to spawn namer and pass it PrimeLord when it sees What is your name. However what happens is namer is called. I see PrimeLord printed to STDOUT. Then I see What is your name: printed to the screen and then the program just exits. I thought maybe I was printing the answer to my expect too soon, but even when I move it after the expect line it didn't work. This seems like it should be very simple, but I just can't get it. Any help would be very appreciated. Thanks!

-Prime

Replies are listed 'Best First'.
Re: Expect.pm Help
by robobunny (Friar) on Aug 08, 2002 at 20:11 UTC
    try swapping the order of the last two lines in your first script (you need to find "name:" before you send the name), and add this line at the end of the first script:
    $expect->soft_close();
Re: Expect.pm Help
by kschwab (Vicar) on Aug 08, 2002 at 20:23 UTC
Re: Expect.pm Help
by belkajm (Beadle) on Aug 09, 2002 at 02:11 UTC

    Ok, as far as I can see, there are two modes that you can can use Expect in. These are the normal and raw pty modes:

    Normal mode (default)
    In this mode all strings sent to the spawned command are echoed back to the pty. Also, these strings will be queued up for the expect commands. Therefore, the following code:
    print $expect "StringToSend"; $expect->expect(15,"StringToWatchFor") or die "not found";
    might not do what you want. If the StringToSend to does not contain the StringToWatchFor then all will be ok. Otherwise the expect call will return from the sent string, not what might have been displayed by the spawned task. In this case, the best I can come up with would be to add another expect line, this time with the StringToWatchFor matching the previous StringToSend exactly.

    If you do not have control over the actions of the spawned process, and you want the send strings to appear on the screen, then you will need to use this mode, and be careful over your expect calls. If either of the above is not the case, then I would use the raw mode, described below.

    Raw mode
    This mode has to be manually activated, and needs to be done before the spawn occurs. Therefore, instead of:

    my $expect = Expect->spawn(....)

    you need to do this:
    my $expect = new Expect; $expect->raw_mode(1); $expect->spawn(....);
    One thing to note about raw mode, is that CR->LF translation will no longer be active. If you don't want this to happen, then there is a suggestion in the docs for disabling echo without activating raw mode, but I haven't tried it:

    $expect->slave->stty(qw(-echo));

    Looking at your sample code, the suggested soft_close call, in conjunction with moving the print line to after the expect, will result in the expected results to appear, and is a valid call to use. However, I would probably add another expect call, looking for something that will appear whatever the result of the test; in this case, it would have to be a carriage return. This way you can be sure that the spawned program really has done it's job, whereas soft_close will just wait up to 15 seconds for it to finish before blindly killing it.

    Another way to carry out this example, modified from an example in the docs, is as follows:

    $expect->expect(15,["name", sub { my $self = shift; $self->print("PrimeLord\n"); exp_continue; }], ["\n", sub { exp_continue; }], "\n");
    With this code, the exp_continue is required on each line except the last for the expect to continue processing, and also resets the timeout each time. To continue processing without resetting the timeout, exp_continue_timeout can be used. I have to admit that I haven't looked into how to determine when the processing stopped with this method.

    Hope this has been helpful. Any questions, don't hesitate to ask,
    Yoda