Reputation: 13
I understand the /g flag and I'm able to match a pattern multiple times, but I'm having a difficult time researching this particular question.
Say my string has multiple lines and I want to match a grouped pattern on a line that contains a specific word, but not on a different line that doesn't.
For an example string $test
with multiple lines
Unimportant line.
Important line with !special1! word and !special2! word.
Extra line with !special3! word and !special4! word.
I want to print the two specials on the important line but not the extra line, so the result would be:
special1, special2
I can match every special using /g
my @both = $test =~ /!(.+?)!/g;
print join(', ', @both);
But the output is:
special1, special2, special3, special4
If I try to include the word 'Important'
my @both = $test =~ /Important.+?!(.+?)!/g;
print join(', ', @both);
I just get
special1
I understand it only matches once because 'Important' only occurs once, but I can't figure out how to get the output
special1, special2
Upvotes: 1
Views: 104
Reputation: 66899
There are a number of ways to do this. I think the most solid and flexible approach is to break your string into lines and iterate over that array. Then you can choose how to select what you need and what you want to do with it, at every iteration. For example
my @lines = split '\n', $test;
foreach my $line (@lines)
{
next if $line !~ /^Important/;
my @all_on_line = $line =~ /!(.+?)!/g;
if (@all_on_line)
{
print join(', ', @all_on_line), "\n";
}
}
I assumed that Important
is at the beginning of the wanted line. Adjust as needed. Since it is likely that more is done with data (than just print it) the if
condition checks whether that line actually had the pattern.
Packing this into a single regex is quite a bit more involved.
Upvotes: 2
Reputation: 126742
You can do this in two steps. First isolate the Important line from the string, and then search for the special substrings
Here's an example. It uses for
as a topicaliser, and is essentially doing ($_) = $test =~ /^(.*Important.*)$/m
for every occurrence of Important
Note that this code will report the data from the last line containing Important
if there is more than one
use strict;
use warnings 'all';
my $test = <<END;
Unimportant line.
Important line with !special1! word and !special2! word.
Extra line with !special3! word and !special4! word.
END
my @both;
@both = /!([^!]+)!/g for $test =~ /^(.*Important.*)$/m;
print join(', ', @both), "\n";
special1, special2
Upvotes: 1
Reputation: 2589
This is also helpful with mapping function:
my @nwlines = map{ $_=~m/^Important(.+?(?=\!special).+?)$/mi } @lines;
Upvotes: 0