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

I'm entering a command on a cisco-like device using Net::Telnet::Cisco. If I run the command by hand I see the output as follows
device#upgrade all ftp://anonymous@release.network.com/tagged/soc/OS.S +6K.V7_1T40 Fetching ftp://anonymous@release.network.com/tagged/soc/OS.S6K.V7_1T4F +ile size is 37548064 bytes ###################################################################### +################################################# ##############[OK] Download complete, file length is 37548064 bytes Forcing image installation... 'V7_1T40' will be next image to boot Upgrade complete: Use the 'reload' command to have upgrade take effect device#
but for some reason when I use the following
@output = $net_tel_cisco->cmd( String => "$params->{cmd}\n", Cmd_remove_mode => 1, Timeout => $params->{timeout}, Prompt => '/(?m:.*[\w.-]+\s?(?:\(config[^\)]*\))?\s?[\ +$#>]\s?(?:\(enable\))?\s*$)/' );
I'm not capturing everything in the @output, Just the first two lines.

The problem seems to be that the prompt regex is matching the following (checked by looking at $net_tel_cisco->last_prompt)
File size is 37548064 bytes #
So I guess, the question is......how can I fix the regex so that it doesn't see that line with multiple #### as a prompt. Maybe only expect a single # as an indication of a prompt?

Replies are listed 'Best First'.
Re: Net::Telnet::Cisco and prompt regex issue
by josh803316 (Beadle) on Dec 09, 2010 at 05:44 UTC
    I tried this right after I posted and it seems to work:
    Prompt => '/(?m:.*[\w.-]+\s?(?:\(config[^\)]*\))?\s?[\$#?>]\s?(?:\(ena +ble\))?\s*$)/'
      / (?m: # not capture, multiline .* # skip anything [\w\.-]+ # the 'device' name part \s? (?:\(config[^\)]*\))? # random '(config...)' part \s? [\$#?>] # real prompt end part \s? (?:\(enable\))? \s* # random '(enable)' part $) /x

      You're missing the '\' escape of the '.' in the device part. It's supposed to be a hostname like thing: foo-bar.baz10.com and needs to match a literal period '\.'.

      You also may need to set the timeout a bit longer depending on how long it takes to download.

      What you really want to do is know the device name in advance, or get it from the last-prompt after you login. Then replace the [\w\.-]+ part of the regex with the actual name of the device.

        You're missing the '\' escape of the '.'

        The dot isn't special inside of a character class, so no escaping required:

        $ perl -E 'say "matched" if "foo-bar.baz" =~ /^[\w.-]+\z/' matched $ perl -E 'say "matched" if "foo-bar:baz" =~ /^[\w.-]+\z/'

        The second case (with ':' in place of '.') doesn't match, because the (unescaped) dot in the pattern stands for a literal dot, not "any character" as it would outside of character classes.

      I spoke too soon, that didn't solve it