Ankur Agarwal
Ankur Agarwal

Reputation: 24748

Perl regex question

How can I match and store the various lines in this string in $1 , $2 and $3 variables in Perl?

$string = "This is a line 1.\nThis is line 2.\nThis is line 3.\n";

I know I have to use the /m modifier but so far my attempts have been unsuccessful.

I tried

$string =~ m/^(.*?)$.^(.*?)$.^(.*?)$/sm;

and other combinations to no avail. I want to keep it simple, so any answers pointing out mistakes would be helpful. I want to only try and use /s and /m modifiers.

Upvotes: 0

Views: 187

Answers (6)

redbmk
redbmk

Reputation: 4796

If you want to use the variables $1, $2, and $3, you can do this by creating a regex string that doesn't see $. as a variable.

my $string = "This is a line 1.\nThis is line 2.\nThis is line 3.\n";
my $rex = q/^(.*?)$.^(.*?)$.^(.*?)$/; #The . between $ and ^ is the newline
$string =~ m/$rex/sm;

To show that this is correct, you can use Data::Dumper.

use Data::Dumper;
print Dumper($1,$2,$3);

This will output:

$VAR1 = 'This is a line 1.';
$VAR2 = 'This is line 2.';
$VAR3 = 'This is line 3.';

To go one step further and show that the . between $ and ^ is matching the newline, you can add the following:

$rex = q/^(.*?)$(.)^(.*?)$(.)^(.*?)$(.)/;
$string =~ m/$rex/sm;

print Dumper($1,$2,$3,$4,$5,$6);

This will output:

$VAR1 = 'This is a line 1.';
$VAR2 = '
';
$VAR3 = 'This is line 2.';
$VAR4 = '
';
$VAR5 = 'This is line 3.';
$VAR6 = '
';

Upvotes: 0

Axeman
Axeman

Reputation: 29844

my ( $first_line, $second_line, $third_line, $rest_if_any ) 
    = split( /\n/m, $string, 4 )
    ;

Upvotes: 1

Ankur Agarwal
Ankur Agarwal

Reputation: 24748

OK I found it. $. being treated as a variable was the clue. I used:

$string =~ m/^(.*?)$(.)^(.*?)$(.)^(.*?)$/sm;

and printed $1, $3, $5.

Thanks all.

Upvotes: 0

Jacek Kaniuk
Jacek Kaniuk

Reputation: 5229

I fixed your regexp:

$string =~ m/^(.*?)\n(.*?)\n(.*?)$/sm;

'$.' was threated as variable (warnings with use warnings; use strict;)

BTW - assining them to an array:

my @list = $string =~ m/^(.*?)\n(.*?)\n(.*?)$/sm;

Upvotes: 2

James
James

Reputation: 41

What's going on is $. is parsed as a variable (its one of those special ones; line number in input file):

$. = "foo";
print "matched" if ("foo" =~ m/$./);

A workaround is using some more syntax to force parsing $ as a regex with (?:$). But that's ugly. I'd just match the new line directly (or use split):

$string =~ m/^(.*)\n(.*)\n(.*)$/;

Upvotes: 4

hmakholm left over Monica
hmakholm left over Monica

Reputation: 23332

Why use $ and ^ to match the intermediate newlines at all? It would be simpler to do

$string =~ m/^(.*)\n(.*)\n(.*)/ ;

with neither /m nor /s. Or even simply

($a,$b,$c) = split /\n/,$string ;

Upvotes: 6

Related Questions