midiperl has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to use a single regex to capture 2 unique patterns
from a text file. The patterns are not on the same line of text.

---Example Text File Start---

First line of the file used for filler
#augment:A Something One
Another line of text for filler
#augment:B Something Two
Last line of the file used for filler

---Example Text File End---

I want to capture the text 'Something One'
and 'Something Two', from the file using a single regex

Perl script snippet showing problem

open my $pf, '<', $file or die "ERROR: Cannot open input file: $file $ +!\n"; my $newvar; #chomp (my @array = (<$pf>)); my @array = (<$pf>); foreach (@array) { $newvar .= $_; } #Attempt to capture just one pattern $newvar =~ /(?:#augment:A)(.*)(?:\n)/; say $1; #this works, printed to standard output is: ' Something One' as I hope +d for #Attempt to capture just one pattern $newvar =~ /(?:#augment:B)(.*)(?:\n)/; say $1; #this works, printed to standard output is: ' Something Two' as I hope +d for #Attempt to capture 2 patterns by combining above regex's $newvar =~ /(?:#augment:A)(.*)(?:\n)(?:#augment:B)(.*)(?:\n)/ ; say $1; say $2; #Does not work - nothing is captured and I get uninitialized value $1 +and $2 warnings...

Note: I also tried using a while loop to read the file in
line by line and match each line against the combined regex - but that did
not capture both patterns either.
Is it possible to capture both patterns in a case like this using
a single regex expression in perl?

Replies are listed 'Best First'.
Re: regex capture group problem
by Athanasius (Archbishop) on Aug 20, 2015 at 03:24 UTC

    Hello midiperl,

    I also tried using a while loop to read the file in line by line and match each line against the combined regex - but that did not capture both patterns either.

    Well, since you specify that The patterns are not on the same line of text, the following approach also works:

    use strict; use warnings; use feature 'say'; while (<DATA>) { say $1 if /#augment:(?:A|B)(.*)/; } __DATA__ First line of the file used for filler #augment:A Something One Another line of text for filler #augment:B Something Two Last line of the file used for filler

    Output:

    13:20 >perl 1350_SoPW.pl Something One Something Two 13:21 >

    P.S. Please fix the formatting of your post by changing <\code> to </code>.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: regex capture group problem
by 1nickt (Canon) on Aug 20, 2015 at 05:28 UTC

    #Attempt to capture 2 patterns by combining above regex's $newvar =~ /(?:#augment:A)(.*)(?:\n)(?:#augment:B)(.*)(?:\n)/ ; say $1; say $2; #Does not work - nothing is captured and I get uninitialized value $1 and $2 warnings...

    You've been shown why this is not matching as you want, but please also consider that $1 and $2 are only uninitialized because you haven't previously successfully captured a match in your program. If you had, those variables would still contain the matches they captured earlier.

    From perlre:

    NOTE: Failed matches in Perl do not reset the match variables, which m +akes it easier to write code that tests for a series of more specific + cases and remembers the best match.

    Thus it's important to check whether the match succeeded before using $1:

    #!/usr/bin/perl use strict; use warnings; my $status = "it's a beautiful day but I am feeling crapy"; # note typ +o $status =~ /(beautiful|average|tough)/; print "Day: $1\n"; $status =~ /(happy|alright|crappy)/; print "Feeling: $1\n"; __END__
    The above code does not give the expected results:
    [22:08][nick:~/monks]$ perl 1139246.pl Day: beautiful Feeling: beautiful [22:08][nick:~/monks]$
    Add a test and we avoid the bug:
    #!/usr/bin/perl use strict; use warnings; my $status = "it's a beautiful day but I am feeling crapy"; # note typ +o if ( $status =~ /(beautiful|average|tough)/ ) { print "Day: $1\n"; } else { print "No match for day\n"; } if ( $status =~ /(happy|alright|crappy)/ ) { print "Feeling: $1\n"; } else { print "No match for feeling\n"; } __END__
    Output:
    [22:13][nick:~/monks]$ perl 1139246.pl Day: beautiful No match for feeling [22:13][nick:~/monks]$

    The way forward always starts with a minimal test.
Re: regex capture group problem
by Anonymous Monk on Aug 20, 2015 at 03:03 UTC
    #!/usr/bin/perl # http://perlmonks.org/?node_id=1139246 use strict; use warnings; $_ = join '', <DATA>; /#augment:A(.*)[\0-\377]*?#augment:B(.*)/ and print "$1 $2\n"; __DATA__ First line of the file used for filler #augment:A Something One Another line of text for filler #augment:B Something Two Last line of the file used for filler
Re: regex capture group problem
by midiperl (Initiate) on Aug 20, 2015 at 16:52 UTC

    Thank You all for the replies, this all helped very much