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

O’Holy and knowledgeable Ones,….Greetings.

I have this simple data
show tech-support details -------------------- show switchname ------------------ CCC217_ANG_GREEN ****************************************************************** -------------------- show interface brief ------------------ ---------------------------------------------------------------------- +--------- mgmt0 up 10.33.81.54/20 100 Mbps 1500 ---------------------------------------------------------------------- +--------- Interface Vsan Admin Status Oper Oper IP Trunk Mode Speed Address Mode (Gbps) ---------------------------------------------------------------------- +--------- port-channel 1 1050 on trunking TE 4 -- port-channel 3 1 on trunking TE 2 -- ******************************************************************
And I have this equally simple code
#! c:/perl/bin/perl.exe use strict; #undef $/; #local $/; my $eof_tmp = $/; #$/=""; open (FILE,"$ARGV[0]") || die "\n$!: $ARGV[0]\n"; my $Rec = {}; while (my $Info = <FILE>) { undef $/; $Rec->{Switchname} = $1 if ($Info =~ /-+ show switchname -+\n(\w+)/ +sm); $/ = $eof_tmp; $Rec->{PortChannel_Num} = $1 if ($Info =~ /^(port-channel \d+)$/); + } print "Switch Name: \t$Rec->{Switchname}\n"; print "Port Channel Number: \t$Rec->{PortChannel_Num}\n";
The strange thing is; if I comment out undef $/ or local $/; then I would only get a value to either $Rec->{Switchname} or $Rec->{PortChannel_Num}! Never both at the same time! Not really sure why is this. I have tried anony-hashes before and they always worked, but not on this occasion.

Can someone please enlighten me on why is this happening and how can I remedy this problem?

Thanks

Blackadder

Replies are listed 'Best First'.
Re: $/ is playing havoc with my script.
by japhy (Canon) on Sep 26, 2005 at 13:02 UTC
    The ONLY thing $/ effects is reading from a filehandle. To change it (and then restore it) inside your while loop has no effect! Its value defines how <FH> operates.

    "----switchname----" and the part you actually want to match are on different lines; thus, reading the file one line at a time, you can't match what you want the regex as you've shown. Also, your PortChannel_Num regex doesn't seem to work, since there is no line that consists solely of "port-channel (DIGITS)".

    Here is a potential solution:

    my %record; while (<FILE>) { if (/----switchname----/) { chomp($record{switchname} = <FILE>); } elsif (/^port-channel (\d+)/) { $record{channel} = $1; } }

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: $/ is playing havoc with my script.
by graff (Chancellor) on Sep 26, 2005 at 13:09 UTC
    Setting $/ to undef causes the next read on any file handle to be done in "slurp" mode -- i.e. everything from the current file offset pointer to the end of file gets pulled in as a single scalar value. Usually, this is done before the first read on a file handle, so the full content of the file comes in as a scalar on one read operation.

    Setting $/ to something and then setting it back to its previous value, without doing any file input between those two settings, has no effect on anything -- so those two lines assigning to $/ within your while loop are pointless.

    In scripts that use modules or that manage more than one input file, it is best to localize changes to $/ within the smallest essential code block, like this:

    my $filecontents; if ( open( FILE, "whatever" )) { local $/; # this sets $/ locally to undef within this block $filecontents = <FILE>; close FILE; } else { die "whatever: $!"; } # all data from "whatever" is now contained in $filecontents # and $/ is now back to its previous value
    There are other idioms involving "do { ... }", which would be easy to find here with SuperSearch.

    (updated code snippet to fix missing paren)

Re: $/ is playing havoc with my script.
by sauoq (Abbot) on Sep 26, 2005 at 13:17 UTC

    Seems japhy gave you your answers. I just thought I'd help clear up a little confusion you seem to have about regular expressions... Your pattern, /-+ show switchname -+\n(\w+)/sm, indicates you don't understand the /m and /s modifiers. The /s modifier is only relevant when your pattern uses a dot (.) in which case it makes the dot match a newline as well as any other character. The /m modifier is only relevant when your pattern uses anchors (^ or $) in which case it'll make the anchors match before and after embedded newlines rather than only at the beginning or end of the whole string.

    -sauoq
    "My two cents aren't worth a dime.";
    
      I believe [id://TheDamian] recommends in Perl Best Practices to use msx on every regex. Of course I don't know if that's what is going on here, but I find it to be good advice; it doesn't hurt anything to have them on there, and if you add a "." to your regex someday it'll work by default (assuming that "works" means ". matches a newline", which it does to me intuitively). I've been bitten by "." not matching a newline before.

      According to Apocalypse 5, in Perl6 "." will always match newline, and ^ and $ will always have a single meaning, so we thankfully won't have this problem.

        Well, if that's what he actually recommends, I'll politely ignore his recommendation. Most of the time you don't need /s or /m. They're useless if you aren't working with multi-line strings. If you are working with multi-line strings, then you may very well want either the behavior you get with them or without them. In that case, you really should know exactly what you are trying to do and use them or not as is fitting, not because you read a book that said use them by default. IMHO, of course.

        -sauoq
        "My two cents aren't worth a dime.";
        

        Just be careful you know why you're doing something, otherwise you're just Cargo cult programming. Which, I've noticed, can be quite frowned upon around here. Although I've never seen anyone accuse followers of TheDamian or merlyn's styles called for Cargo culting before.