Я подозреваю, что есть более простой способ сделать все, что вы пытаетесь достичь. Хитрость заключается не в том, чтобы сделать код генерации регулярных выражений настолько хитрым, чтобы вы забыли, что он на самом деле делает.
Я могу только начать догадываться о вашей задаче, но из вашего единственного примера похоже, что вы хотите проверить, что два субтокена находятся в большем токене, игнорируя определенные символы. Я предполагаю, что эти суб-токены должны быть в порядке и между ними не должно быть ничего кроме этих гласных символов.
Чтобы сопоставить токены, я могу использовать якорь \G
с глобальным флагом /g
в скалярном контексте. Это привязывает совпадение к персонажу после окончания последнего совпадения для того же скаляра. Этот способ позволяет мне иметь отдельные шаблоны для каждого вспомогательного токена. Это намного проще в управлении, поскольку мне нужно всего лишь изменить список значений в @subtokens
.
Как только вы пройдете каждую из пар и найдете, какие из них соответствуют всем образцам, я могу извлечь исходную строку из пары.
use v5.14;
my $vowels = '[ao]*';
my @subtokens = qw(bEd mA);
# prepare the subtoken regular expressions
my @patterns = map {
my $s = join "$vowels", map quotemeta, (split( // ), '');
qr/$s/;
} @subtokens;
my @tokens = qw( baEodamA mAabaEod baEoda mAbaEoda );
my @grand_matches;
TOKEN: foreach my $token ( @tokens ) {
say "-------\nMatching $token..........";
my @matches;
PATTERN: foreach my $pattern ( @patterns ) {
say "Position is ", pos($token) // 0;
# scalar context /g and \G
next TOKEN unless $token =~ /\G($pattern)/g;
push @matches, $1;
say "Matched with $pattern";
}
push @grand_matches, [ $token, \@matches ];
}
# Now report the original
foreach my $tuple ( @grand_matches ) {
say "$tuple->[0] has both fragments: @{$tuple->[1]}";
}
Теперь, вот что хорошо в этой структуре. Я, вероятно, неправильно угадал о вашей задаче. Если у меня есть, это легко исправить без изменения настроек. Допустим, субтокены не должны быть в порядке. Это легко изменить шаблон, который я создал. Я просто избавляюсь от
\G
якорь и флаг /g
;
next TOKEN unless $token =~ /($pattern)/;
Или предположим, что жетоны должны быть в порядке, но между ними могут быть другие вещи. Я могу вставить .*?
, чтобы соответствовать этому материалу, фактически пропуская его:
next TOKEN unless $token =~ /\G.*?($pattern)/g;
Было бы намного лучше, если бы я мог справиться со всем этим с map
, где я создаю шаблоны, но флаг /g
не является флагом шаблона. Это должно идти с оператором.
Мне гораздо легче управлять изменяющимися требованиями, когда я не заключаю все в одно регулярное выражение.