Reputation: 24748
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
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
Reputation: 29844
my ( $first_line, $second_line, $third_line, $rest_if_any )
= split( /\n/m, $string, 4 )
;
Upvotes: 1
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
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
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
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