user105265
user105265

Reputation: 29

Extract values after match a keyword

I would like to extract values after I match the keyword "coor" multiple times in a string. My code doesn't do that at all. Can anyone help me to fix it please?

My code:

my $str = ;
if ($str =~ /$keyword/)
{
  if ($' =~ /\[/) #'# everything after the matched string
  {
    $str=~ /\(coor\s(\d+)\s(\d+)\)\s\(coor\s(\d+)\s(\d+)\)\s\(coor\s(\d+)\s(\d+)\)\s\(coor\s(\d+)\s(\d+)\)\s/;
    {
      open( my $file, '>>', $filename );
      print {$file} $1, " ";
      print {$file} $2, " ";
      print {$file} $3, " ";
      print {$file} $4, " ";
      print {$file} $5, " ";
      print {$file} $6, " ";
      print {$file} $7, " ";
      print {$file} $8, " ";
      close( $file );
    }
  }
}

This is my input string:

[(beginKey object1 (coor 141 257) (coor 1315 254) (coor 1313 430) (coor 140 420) [] [] []), (beginKey keyword (coor 2035 253) (coor 1315 254) (coor 1313 430) (coor 2034 436) [] [] [])].

Upvotes: 1

Views: 553

Answers (4)

Greg Bacon
Greg Bacon

Reputation: 139601

Using Perl's \G anchor in scalar context is useful in this case because it continues where a previous //g match left off:

if (/keyword/g) {
  my @coor;

  while (/\G\s*\(coor (\d+) (\d+)\)/g) {
    push @coor => [$1, $2];
  }

  for (@coor) {
    print "@$_\n";
  }
}

With $_ set to your sample input, the code above outputs

2035 253
1315 254
1313 430
2034 436

Upvotes: 2

MadH
MadH

Reputation: 1508

Hmm, I don't see a problem with your current code.

offtopic: in Qt, QRegExp has a method int MatchedLength() - very easy to see how much of your string was matched.

Upvotes: 0

Eric Darchis
Eric Darchis

Reputation: 26717

You need to escape the special characters in the regex:

(coor (1) (2)) => \(coor (1) (2)\)

same for /[/ that is a syntax error => /[/

Here is my modified version of your script, the regex is fixed, I split the string on ',' to match the intended keyword and the regex result is tested:

#!/usr/bin/perl
my $keyword = "object1";
my $str = "[(beginKey object1 (coor 141 257) (coor 1315 254) (coor 1313 430) (coor 140 420) [] [] []), (beginKey keyword (coor 2035 253) (coor 1315 254) (coor 1313 430) (coor 2034 436) [] [] [])].";
my @entries=split(',', $str);
foreach my $entry (@entries)
{
  if ($entry =~ /$keyword/)
  {
    my $tomatch=$';
    if ($tomatch =~ /\(coor\s(\d+)\s(\d+)\)\s\(coor\s(\d+)\s(\d+)\)\s\(coor\s(\d+)\s(\d+)\)\s\(coor\s(\d+)\s(\d+)\)\s/)
    {
      print $1," ";
      print $2," ";
      print $3," ";
      print $4," ";
      print $5," ";
      print $6," ";
      print $7," ";
      print $8," ";
    }
    else
    {
      print "no match !";
    }
  }
}

This prints:

141 257 1315 254 1313 430 140 420 

Upvotes: 1

ysth
ysth

Reputation: 98398

[ is a special character inside a regex, so your second match needs to be against /\[/ to match a literal [.

Your third match has 12 sets of capturing parentheses; I'm guessing you want /coor\s(\d+)\s(\d+)\scoor\s(\d+)\s(\d+)\scoor\s(\d+)\s(\d+)\scoor\s(\d+)\s(\d+)/ instead. You also should check that the match succeeded before using $1, etc.

Upvotes: 0

Related Questions