in reply to Repeated Pattern Matching Fails

The immediate reason that this very complex regex stops where it does is that it doesn't take into account the possibility of "S.txt" in the middle of the line. Thus it stops matching when it bumps into that part of the line. Only matches in the part before "S.txt" are getting printed out. However, even without that annoying "S.txt", there are several other problems with your regex and I also wonder if we might have an XY Problem.

Judging by your response to targetsmart and the code you've shown above, you seem to just want to strip the introductory label and replace runs of spaces with "==". if that is the case then why not do something simple like this:

my $sNoLabel = substr($var, length("FILES CHECKED IN:")); $sNoLabel =~ s/\s+/==/g; print "MATCH$sNoLabel\n";

On the other hand, if you wanted to do something else, e.g. print out "TEST" and the version numbers but skip past that pesky "S.txt", then it might help to understand a bit better what the regex you currently have is doing. I have a feeling it is not what you think:

Putting this altogether here is how we would capture "TEST" and the revision numbers, but skip past "S.txt":

#move match start forward to after label # g tells Perl to save the point where we stopped matching $var =~ /^FILES CHECKED IN:\s+/g; #capture label and move match start to after TEST my ($sName) = ($var =~ /(\w+)/g); #capture the remaining revision numbers (ignore S.txt) my @aRevnums = ($var =~ /(\d+\.\d+(?:\.\d+)*)/g); print "$sName: @aRevnums\n";

Best, beth

Replies are listed 'Best First'.
Re^2: Repeated Pattern Matching Fails
by kapila (Acolyte) on Apr 14, 2009 at 11:40 UTC

    Thanks Beth & Parv for your replies. Beth thanks for correcting me in my pattern. I basically require a pattern wherein, it matches the lines-

    $var="Files Checked IN: test/abc.txt 1.23 1.3.4.5 team/hello.cpp 2.1 NONE Clear/thing.pl NONE 1.2.34 etc etc";

      You don't need a pattern for that, split will do:

      use Data::Dumper; my %found; while (<DATA>) { my ($file, @vers) = split " "; if (-f $file) { $found{$file} = [ @vers ]; } } print Dumper(\%found); __DATA__ Files Checked IN: test/abc.txt 1.23 1.3.4.5 team/hello.cpp 2.1 NONE Clear/thing.pl NONE 1.2.34 etc etc

      Output:

      $VAR1 = { 'Clear/thing.pl' => [ 'NONE', '1.2.34' ], 'team/hello.cpp' => [ '2.1', 'NONE' ], 'test/abc.txt' => [ '1.23', '1.3.4.5' ] };

      You write

      Need to call this pattern in one line..(requirement of my script)

      Do you mind to tell why you do have such a requirement?

      <update>

      Anyways, you want the /g modifier on your pattern, and thus you can't say

      if ( $var =~ m{$pattern}g ) {

      because that will match only once (but without resetting the match location). If you really have to match globally and evaluate the result in a scalar (or boolean) context, you have to write something like

      if ( (@matches = $var =~ m{$pattern}g ) > 0) {

      which is ugly and not very readable. Anyways, here it is...

      $var="Files Checked IN: test/abc.txt 1.23 1.3.4.5 team/hello.cpp 2.1 NONE Clear/thing.pl NONE 1.2.34 etc etc"; my $pattern = '([\w./]+)\s+([\d.]+|NONE)\s+([\d.]+|NONE)'; if ( ( @matches = $var =~ m{$pattern}g ) >0 ) { print join('|',@matches),$/; }

      </update>