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

Problems with a regex?

by dwlepage (Novice)
on Aug 14, 2012 at 15:20 UTC ( [id://987380]=perlquestion: print w/replies, xml ) Need Help??

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

Hi, I'm stuck on something and was hoping someone could shed some light. I'm attempting to match on a certain value stored in an array but for whatever reason it will not match. Here is the code:
#Parse the Netscreen configuration open (NETSCREEN, "<net.config") || die "Cannot open file: $!\n"; my %netscreenServices = (); my @stack; foreach my $line (<NETSCREEN>) { chomp $line; if ($line =~ m/set\sservice\s(\".+\").?/) { my $serv = $1; print "Service name: $serv\n"; if (&check_stack($serv)) { print "It's on stack, keep compiling\n"; } else { print "Popping stack: @stack. Adding to stack: $1\n"; pop(@stack); push(@stack, $1); } } #print "$line\n"; } close (NETSCREEN); ###################################################################### +############# # Subfunctions ###################################################################### +############# #Checks the last element on the stack. Netscreen services are piled in +to multiple lines so we #need to keep track of the last entry. #Return TRUE if the last item is on the stack sub check_stack { my $stack = $_[0]; if (grep(/^$stack$/, @stack)) { return 1; } else { return 0; } }

__DATA__
set service "MY NEW SERVICE (TMP)" protocol tcp src-port 0-65535 dst-port 4103-4103
set service "MY NEW SERVICE (TMP)" + tcp src-port 0-65535 dst-port 4105-4105

When I run it I get:
Service name: "MY NEW SERVICE (TMP)"
Popping stack: . Adding to stack: "MY NEW SERVICE (TMP)"
Service name: "MY NEW SERVICE (TMP)"
Popping stack: "MY NEW SERVICE (TMP)". Adding to stack: "SGID IMAGE SERVER (TMP)"

For some reason the value is not matching in the subroutine. It seems to have something to do with the parens in the string but i'm at a loss. Does anyone have an idea?

Replies are listed 'Best First'.
Re: Problems with a regex?
by BrowserUk (Patriarch) on Aug 14, 2012 at 15:28 UTC

    Change     if (grep(/^$stack$/, @stack)) { to     if (grep(/^\Q$stack$/, @stack)) {.

    perlre for details.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

    The start of some sanity?

      To /^\Q$stack\E$/ (emphasis on the \E).

      And to the OP, note that your first RE can be simplified:

      #if ($line =~ m/set\sservice\s(\".+\").?/) { if ($line =~ m/set\sservice\s(".+")/) {

      No need to escape quotes; nor to match beyond what you are interested in. (I often see REs with a useless .* at the end.)

        To /^\Q$stack\E$/ (emphasis on the \E).

        Why? If the \E comes at the end of the regex it is completely redundant. A pointless, useless addition.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        The start of some sanity?

Re: Problems with a regex?
by AnomalousMonk (Archbishop) on Aug 14, 2012 at 16:17 UTC

    Further to BrowserUk's Re: Problems with a regex?:
    The  /^\Q$stack$/ regex is equivalent to a  $string eq $_ string equality test. Also,   List::MoreUtils::any   is, IMO, better than the OPed usage of grep from the standpoint of self-documentation and maintainability (and it's also terse enough that it may not need to be encapsulated in another function).

    >perl -wMstrict -le "use List::MoreUtils qw(any); ;; my @ra = qw(foo BAR baz quux boff); ;; for my $string (qw(BAR bar xyzzy)) { print qq{'$string' is }, check_stack($string, \@ra) ? '' : 'NOT ', qq{in (@ra)}; } ;; sub check_stack { my ($string, $array_ref) = @_; return any { $string eq $_ } @$array_ref; } " 'BAR' is in (foo BAR baz quux boff) 'bar' is NOT in (foo BAR baz quux boff) 'xyzzy' is NOT in (foo BAR baz quux boff)
Re: Problems with a regex?
by 2teez (Vicar) on Aug 14, 2012 at 16:32 UTC
    Why not just use smart match instead of grep like so:
    sub check_stack { my $stack = $_[0]; if ($stack ~~ @stack) { return 1; } else { return 0; } }
      Thanks everyone. This helped a lot.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://987380]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2024-04-25 14:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found