in reply to A regex question.

Because you're using the  /g regex modifier for all matches, the string match position never resets to the start of the string, but advances for each and every match performed. (Update: I should have written: advances for each and every successful match performed.)

c:\@Work\Perl\monks>perl -wMstrict -le "my $s = 'xx111yy22xx333yy44zz555xx666'; ;; print qq{first capture: '$1'} if $s =~ m{ (\d+) }xmsg; ;; print qq{subsequent captures: '$1'} while $s =~ m{ (\d+) }xmsg; " first capture: '111' subsequent captures: '22' subsequent captures: '333' subsequent captures: '44' subsequent captures: '555' subsequent captures: '666'
The fact that the first match in the OPed code is a negative | negated match (so no action is taken) does not matter; it's still a  /g match against the same string. Eliminating the  /g modifier on the first match will cause string match position to be reset before subsequent matches (which must still use /g).

Note that use of the  /g modifier in an
    if ($string =~ m{ ... }xmsg) { ... }
statement is useless except as a way to introduce exactly the behavior you are seeing!

Update: A number of incremental updates made.


Give a man a fish:  <%-(-(-(-<

Replies are listed 'Best First'.
Re^2: A regex question.
by Anonymous Monk on Jul 31, 2015 at 23:57 UTC

    Hm, well I really didn't understand that about how the match operator works so I guess that would explain it. I had assumed /g was pointless on the if after thinking about it, but the part I really couldn't figure out was why the negative match would affect the subsequent one in any way.

      Hello FeistyLemur, and welcome to the Monastery!

      See the section “Global matching” in perlretut#Using-regular-expressions-in-Perl, and in particular note the following (emphasis added.):

      In scalar context, successive invocations against a string will have //g jump from match to match, keeping track of position in the string as it goes along....
      A failed match or changing the target string resets the position.... The current position in the string is associated with the string, not the regexp.

      Hope that helps,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        Yes, I understand now why I was seeing the behavior in question. Things are working as I intended in my script. I just wanted to understand what I was missing about the match operator. I didn't realize the position in the string was associated with the string and not the regexp.

        I got the answer I was looking for and understand the match operator better now, thanks.

      ... the negative match ...

      It's important to understand that the negation is made on the result of the  /eth1\.\d{4}\@/gm match against the  $ethernet string. The match itself is actually successful! It's as if the
          if ($ethernet !~ /eth1\.\d{4}\@/gm) { ... }
      statement had been written as
          if ( ! ($ethernet =~ /eth1\.\d{4}\@/gm)) { ... }
      (note =~ vice !~). In fact, that's pretty much the way Perl sees the code:

      c:\@Work\Perl\monks>perl -wMstrict -MO=Deparse,-p -le "my $ethernet=`ip addr`; if ($ethernet!~/eth1\.\d{4}\@/gm){ print qq{No vlans exist on device.\n}; exit; } " BEGIN { $^W = 1; } BEGIN { $/ = "\n"; $\ = "\n"; } use strict 'refs'; (my $ethernet = `ip addr`); unless (($ethernet =~ /eth1\.\d{4}\@/gm)) { print("No vlans exist on device.\n"); exit; } -e syntax OK

      I had assumed /g was pointless on the if ...

      Given what you were trying to do, it was pointless, but it was not without effect!


      Give a man a fish:  <%-(-(-(-<