http://www.perlmonks.org?node_id=1004231


in reply to Capturing all instances of a repeating sub-pattern in regex

It seems odd that you are doing all this in a substitution rather than iterating over the results of the match, e.g. while ($text =~ /$re/g) {...}, particularly given that you are already resorting to some complex activity including an e modifier. However, you could do this in a fell swoop by capturing the entire block you want to reparse, and using a sub-regex in list context w/ the g modifier to return the full list:

$text =~ s/ (.+?) (?:\s*\n)+ ((?: \d+ (?:\sPSI)? (?:\s*\n)+ ){4}) /push @r, [ $1, $2 =~ m|\d+ (?:\sPSI)?|xg ]/esgx;

If I were the maintenance guy that followed you, I would not think friendly thoughts when I saw that.

You could get something a little more maintainable by explicitly expanding your {4} terms:

$text =~ s/ (.+?) (?:\s*\n)+ (?: (\d+ (?:\sPSI)?) (?:\s*\n)+ ) (?: (\d+ (?:\sPSI)?) (?:\s*\n)+ ) (?: (\d+ (?:\sPSI)?) (?:\s*\n)+ ) (?: (\d+ (?:\sPSI)?) (?:\s*\n)+ ) /push @r, [ $1, $2, $3, $4, $5 ]/esgx;
which could be refactored into
my $sub_re = qr/ (\d+ (?:\sPSI)?) (?:\s*\n)+ /x; $text =~ s/ (.+?) (?:\s*\n)+ $sub_re $sub_re $sub_re $sub_re /push @r, [ $1, $2, $3, $4, $5 ]/esgx;

None of this changes the fact that you have a fundamental obfuscation by using a substitution instead of a loop.


#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.