эффективный способ поиска одного и того же регулярного выражения в нескольких текстах - PullRequest
3 голосов
/ 03 декабря 2011

У меня есть несколько текстовых полей, каждое поле является абзацем текста, и я хочу найти определенный шаблон в этих полях, используя регулярное выражение, например:

my $text1 =~/(my pattern)/ig;
my $text2 =~/(my pattern)/ig;
...
my $textn=~/(my pattern)/ig;

Интересно, есть ли эффективный способ поиска по нескольким текстам с одинаковым регулярным выражением на perl, или мне следует использовать вышеуказанный формат?

Ответы [ 3 ]

13 голосов
/ 03 декабря 2011

Использовать актуализатор.

for ($text1, $text2, $textn) {
    /(my pattern)/ig && do { ... };
}

Если у вас есть пронумерованные переменные, это красный флаг, который вы должны рассмотреть вместо составной структуры данных.С простым массивом это выглядит примерно так же:

for (@texts) {
2 голосов
/ 03 декабря 2011
my $pattern = qr/((?:i)my pattern)/;
my @matches;
push @matches, $text1 =~ /$pattern/g;
push @matches, $text2 =~ /$pattern/g;
push @matches, $textn =~ /$pattern/g;

Это примерно настолько эффективно, насколько я могу себе представить - теоретически предварительно скомпилируем регулярное выражение один раз, хотя я не уверен, что если интерполировать его обратно в //, чтобы модификатор 'g' отменил любую из этих компиляций.Конечно, мне также интересно, действительно ли это узкое место, и если вы просто смотрите на некоторую преждевременную оптимизацию.

0 голосов
/ 03 декабря 2011

Ответ на этот вопрос зависит от того, содержит ли ваш шаблон какие-либо переменные.Если это не так, Perl уже достаточно умен, чтобы создавать RE только один раз, если он везде одинаков.

Теперь, если вы используете переменные, тогда ответ @ Tanktalus близок, но добавляет ненужную сложность,путем компиляции RE дополнительное время.

Используйте это:

my @matches;
push @matches, $text1 =~ /((?:i)my pattern with a $variable)/o;
push @matches, $text2 =~ /((?:i)my pattern with a $variable)/o;
push @matches, $textn =~ /((?:i)my pattern with a $variable)/o;

Почему?

Используя переменную в шаблоне RE, perl вынужден перекомпилироватьдля каждого случая, даже если эта переменная является предварительно скомпилированным RE, как в ответе @ Tanktalus./o гарантирует, что он компилируется только один раз, в первый раз, когда он встречается, но он все равно должен быть скомпилирован один раз для каждого вхождения в коде.Это потому, что Perl не может узнать, изменился ли $ pattern между различными вариантами использования.

Другие соображения

На практике, как сказал @Tanktalus, я подозреваю, что это большой примерпреждевременная оптимизация./o / имеет значение только тогда, когда ваш шаблон содержит переменные (в противном случае Perl достаточно умен, чтобы в любом случае компилироваться только один раз!)

Гораздо более полезная причина использовать предварительно скомпилированный RE, как предложил @Tanktalus, состоит в том, чтобыулучшить читаемость кода.Если у вас большой волосатый RE, то использование $ pattern везде значительно улучшит читабельность, и с минимальными затратами на производительность (которую вы вряд ли когда-либо заметите).

Заключение

Просто используйте /o для ваших RE, если они содержат переменные (если вам не нужны переменные для изменения RE при каждом запуске), и не беспокойтесь об этом в противном случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...