Вы должны использовать чередование регулярных выражений, например:
my @string = qw/abc def ghi/;
my $matcher = qr/@{[join '|', map quotemeta, sort @string]}/;
Это должно быть быстрее, чем при использовании индекса. Но это можно сделать еще быстрее:
До определенного предела, в зависимости как от длины, так и от числа строк, perl создаст tr ie для эффективного сопоставления; см. например https://perlmonks.org/?node_id=670558. Вы захотите поэкспериментировать с тем, сколько строк вы можете включить в одно регулярное выражение для создания массива регулярных выражений. Затем объедините эти отдельные регулярные выражения в одно (непроверенное):
my @search_strings = ...;
my @matchers;
my $string_limit = 3000; # a guess on my part
my @strings = sort @search_strings;
while (my @subset = splice @strings, 0, $string_limit) {
push @matchers, qr/^.*?@{[join '|', map quotemeta, sort @subset]}/s;
}
my $matcher = '(?:' . join('|', map "(??{\$matchers[$_]})", 0..$#matchers) . ')';
$matcher = do { use re 'eval'; qr/$matcher/ };
/$matcher/ and print "line $. matched: $_" while <>;
Конструкция (??{...})
необходима для объединения отдельных регулярных выражений; без этого все под-выражения просто интерполируются, а объединенное регулярное выражение компилируется все вместе, что исключает оптимизацию tr ie. Каждый подгрекс начинается с ^.*?
, поэтому он ищет всю строку; без этого объединенное регулярное выражение должно было бы вызывать каждый подрегекс отдельно для каждой позиции в строке.
Используя искусственные данные, я вижу около 3000 строк, ищущих в секунду с этим подходом в не очень быстром vm. Использование наивного регулярного выражения составляет менее 50 строк в секунду. Использование grep, как предлагается в комментарии Шона, быстрее (для меня это примерно 4200 строк в секунду), но дает вам меньше контроля, если вы хотите делать такие вещи, как определение, какие строки соответствуют или в каких позициях.