27

I have text in the form:

Name=Value1
Name=Value2
Name=Value3

Using Perl, I would like to match /Name=(.+?)/ every time it appears and extract the (.+?) and push it onto an array. I know I can use $1 to get the text I need and I can use =~ to perform the regex matching, but I don't know how to get all matches.

Thomas Owens
  • 114,398
  • 98
  • 311
  • 431
  • Related: http://stackoverflow.com/questions/1034027/how-do-i-access-captured-substrings-after-a-successful-regex-match-in-perl – Sinan Ünür Nov 12 '09 at 16:30

5 Answers5

55

A m//g in list context returns all the captured matches.

#!/usr/bin/perl

use strict; use warnings;

my $str = <<EO_STR;
Name=Value1
Name=Value2
Name=Value3
EO_STR

my @matches = $str =~ /=(\w+)/g;
# or my @matches = $str =~ /=([^\n]+)/g;
# or my @matches = $str =~ /=(.+)$/mg;
# depending on what you want to capture

print "@matches\n";

However, it looks like you are parsing an INI style configuration file. In that case, I will recommend Config::Std.

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
  • 7
    The important thing to note is the `g` at the end of the regular expression. – mob Nov 12 '09 at 16:22
  • Actually, I simplified the format. There's text in the middle, but until I handled the simple case, there was no hope of me handling the larger case. – Thomas Owens Nov 12 '09 at 16:33
9
my @values;
while(<DATA>){
  chomp;
  push @values, /Name=(.+?)$/;
}   
print join " " => @values,"\n";

__DATA__
Name=Value1
Name=Value2
Name=Value3
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
aartist
  • 3,145
  • 3
  • 33
  • 31
  • 6
    Don't use $1 if the regex didn't succeed: `/Name=(.+?)$/ and push @values, $1`. Or even just `my @values = map /Name=(.+?)$/, ;` – ysth Nov 12 '09 at 19:17
5

The following will give all the matches to the regex in an array.

push (@matches,$&) while($string =~ /=(.+)$/g );
Jason Plank
  • 2,336
  • 5
  • 31
  • 40
champ e perl
  • 51
  • 1
  • 1
1

Instead of using a regular expression you might prefer trying a grammar engine like:

I've given a snippet of a Parse::ResDescent answer before on SO. However Regexp::Grammars looks very interesting and is influenced by Perl6 rules & grammars.

So I thought I'd have a crack at Regexp::Grammars ;-)

use strict;
use warnings;
use 5.010;

my $text = q{
Name=Value1
Name = Value2
Name=Value3  
};

my $grammar = do {
    use Regexp::Grammars;
    qr{
        <[VariableDeclare]>*

        <rule: VariableDeclare>
            <Var> \= <Value>

        <token: Var>    Name

        <rule: Value>   <MATCH= ([\w]+) >
    }xms;
};


if ( $text =~ $grammar ) {
    my @Name_values = map { $_->{Value} } @{ $/{VariableDeclare} };
    say "@Name_values";
}

The above code outputs Value1 Value2 Value3.

Very nice! The only caveat is that it requires Perl 5.10 and that it may be overkill for the example you provided ;-)

/I3az/

Community
  • 1
  • 1
draegtun
  • 22,441
  • 5
  • 48
  • 71
1

Use a Config:: module to read configuration data. For something simple like that, I might reach for ConfigReader::Simple. It's nice to stay out of the weeds whenever you can.

brian d foy
  • 129,424
  • 31
  • 207
  • 592