Из ответа perlfaq6 на Как эффективно сопоставить много регулярных выражений одновременно?
Как эффективно сопоставить много регулярных выражений одновременно?
(предоставлено Брайаном Д. Фой)
Если у вас Perl 5.10 или новее, это почти тривиально. Вы просто сопоставляете массив объектов регулярных выражений:
my @patterns = ( qr/Fr.d/, qr/B.rn.y/, qr/W.lm./ );
if( $string ~~ @patterns ) {
...
};
Интеллектуальное совпадение прекращается, когда оно находит совпадение, поэтому не нужно пробовать каждое выражение.
Раньше, чем Perl 5.10, у вас есть немного работы. Вы хотите избегать компиляции регулярного выражения каждый раз, когда хотите его сопоставить. В этом примере perl должен перекомпилировать регулярное выражение для каждой итерации цикла foreach, поскольку он не может знать, каким будет $ pattern:
my @patterns = qw( foo bar baz );
LINE: while( <DATA> ) {
foreach $pattern ( @patterns ) {
if( /\b$pattern\b/i ) {
print;
next LINE;
}
}
}
Оператор qr // появился в perl 5.005. Он компилирует регулярное выражение, но не применяет его. Когда вы используете предварительно скомпилированную версию регулярного выражения, Perl выполняет меньше работы. В этом примере я вставил карту, чтобы превратить каждый шаблон в предварительно скомпилированную форму. Остальная часть скрипта такая же, но быстрее:
my @patterns = map { qr/\b$_\b/i } qw( foo bar baz );
LINE: while( <> ) {
foreach $pattern ( @patterns ) {
if( /$pattern/ )
{
print;
next LINE;
}
}
}
В некоторых случаях вы можете сделать несколько шаблонов одним регулярным выражением. Остерегайтесь ситуаций, которые требуют возврата назад.
my $regex = join '|', qw( foo bar baz );
LINE: while( <> ) {
print if /\b(?:$regex)\b/i;
}
Подробнее об эффективности регулярных выражений см. В статье «Освоение регулярных выражений» Джеффри Фрейдля. Он объясняет, как работает механизм регулярных выражений и почему некоторые шаблоны удивительно неэффективны. Как только вы поймете, как Perl применяет регулярные выражения, вы можете настроить их для отдельных ситуаций.