Используйте именованные группы захвата и присвойте имена подшаблонам с (DEFINE)
, чтобы значительно улучшить читаемость.
#! /usr/bin/env perl
use strict;
use warnings;
use 5.10.0; # for named capture buffer and (?&...)
my $second_trimmed_field_pattern = qr/
(?&FIRST_FIELD) (?&SEP) (?<f2> (?&SECOND_FIELD))
(?(DEFINE)
# The separator is a comma preceded by optional whitespace.
# NOTE: the format simple comma separators, NOT full CSV, so
# we don't have to worry about processing escapes or quoted
# fields.
(?<SEP> \s* ,)
# A field stops matching as soon as it sees a separator
# or end-of-string, so it matches in similar fashion to
# a pattern with a non-greedy quantifier.
(?<FIELD> (?: (?! (?&SEP) | $) .)+ )
# The first field is anchored at start-of-string.
(?<FIRST_FIELD> ^ (?&FIELD))
# The second field looks like any other field. The name
# captures our intent for its use in the main pattern.
(?<SECOND_FIELD> (?&FIELD))
)
/x;
В действии:
my @source = (
"something,something2,third"
,"something,something3 ,third"
,"something,something4"
,"something,something 5" # Note the space in the middle of the word
);
for (@source) {
if (/$second_trimmed_field_pattern/) {
print "[$+{f2}]\n";
#print "[$1]\n"; # or do it the old-fashioned way
}
else {
chomp;
print "no match for [$_]\n";
}
}
Вывод:
[something2]
[something3]
[something4]
[something 5]
Вы можете выразить это аналогично старым perls.Ниже я ограничу части лексической областью действия сабвуфера, чтобы показать, что все они работают вместе как единое целое.
sub make_second_trimmed_field_pattern {
my $sep = qr/
# The separator is a comma preceded by optional whitespace.
# NOTE: the format simple comma separators, NOT full CSV, so
# we don't have to worry about processing escapes or quoted
# fields.
\s* ,
/x;
my $field = qr/
# A field stops matching as soon as it sees a separator
# or end-of-string, so it matches in similar fashion to
# a pattern with a non-greedy quantifier.
(?:
# the next character to be matched is not the
# beginning of a separator sequence or
# end-of-string
(?! $sep | $ )
# ... so consume it
.
)+ # ... as many times as possible
/x;
qr/ ^ $field $sep ($field) /x;
}
Используйте его как в
my @source = ...; # same as above
my $second_trimmed_field_pattern = make_second_trimmed_field_pattern;
for (@source) {
if (/$second_trimmed_field_pattern/) {
print "[$1]\n";
}
else {
chomp;
print "no match for [$_]\n";
}
}
Вывод:
$ perl5.8.8 prog
[something2]
[something3]
[something4]
[something 5]