Это может побрить некоторое время
жадный
([AB]).*(?!\1)[AB]
не жадный
([AB]).*?(?!\1)[AB]
повторить
Я сделал собственные скамейки по этому вопросу.Сопоставление одного члена за раз, например, /term/
, в отличие от двух слагаемых в одном регулярном выражении, всегда будет занимать меньше времени, поскольку не требует
обратного отслеживания.Это так же просто, как strncmp (термин).И выполнение двух терминов по отдельности будет тогда
намного быстрее.
Если вы можете определить термины так, чтобы не было возможности совпадения, тогда это
путь.то есть;/ term1 / && /term2/.
Невозможно объединить термины в одно регулярное выражение, не вызывая возврат.
То есть, если вы действительно заботитесь о перекрытии, то есть методы, чтобы минимизировать
откат.
/ (? =. * A) (? =. * B) / isточно так же, как / A / && / B /, за исключением того, что это выглядит намного медленнее, ни одно из них не учитывает перекрытие.
Итак, если вы действительно заботитесь о перекрытии (и я настоятельно рекомендую вам это сделать), есть
два способа, которые можно комбинировать для максимальной эффективности.
/ (A | B). * (?! \ 1) (?: A | B) /
или
/ A / && / B / && / (A | B). * (?! \ 1) (?: A | B) /
Последний добавит небольшие (относительные) накладные расходы, но может запретить доступ в логической цепочке
, требуя, чтобы A и B по крайней мере существовали, прежде чем проверять наличие совпадений.
И, в зависимости от того, где A и B существуют в строке, / (A |B). * (?! \ 1) (?: A | B) /
также может занять некоторое время, но это все же самый короткий путь, который есть, когда все
усредняется.
Нижепрограмма Perl, которая тестирует некоторые примерные (возможные сценарии) строки.
Удачи!
use strict;
use warnings;
use Benchmark ':hireswallclock';
my ($t0,$t1);
my ($term1, $term2) = ('term','m2a');
my @samples = (
' xaaaaaaa term2ater ',
' xaaaaaaa term2aterm ',
' xaaaaaaa ter2ater ',
' Aaa term2ater ' . 'x 'x100 . 'xaaaaaaa mta ',
' Baa term ' . 'x 'x100 . 'xaaaaaaa mta ',
' Caa m2a ' . 'x 'x100 . 'xaaaaaaa term ',
' Daa term2a ' . 'x 'x100 . 'xaaaaaaa term ',
);
my $rxA = qr/$term1/;
my $rxB = qr/$term2/;
my $rxAB = qr/ ($term1|$term2) .* (?!\1)(?:$term1|$term2) /x;
for (@samples)
{
printf "Checking string: '%.40s'\n-------------\n", $_;
if (/$term1/ && /$term2/ ) {
print " Found possible candidates (A && B)\n";
}
if (/ ($term1|$term2) .* ((?!\1)(?:$term1|$term2)) /x) {
print " Found non-overlaped terms: '$1' '$2'\n";
}
else {
print " No (A|B) .* (?!\\1)(A|B) terms found!\n";
}
print "\n Bench\n";
$t0 = new Benchmark;
for my $cnt (1 .. 500_000) {
/$rxA/ && /$rxB/;
}
$t1 = new Benchmark;
print " $rxA && $rxB\n -took: ", timestr(timediff($t1, $t0)), "\n\n";
$t0 = new Benchmark;
for my $cnt (1 .. 500_000) {
/$rxAB/;
}
$t1 = new Benchmark;
print " $rxAB\n -took: ", timestr(timediff($t1, $t0)), "\n\n";
$t0 = new Benchmark;
for my $cnt (1 .. 500_000) {
/$rxA/ && /$rxB/ && /$rxAB/;
}
$t1 = new Benchmark;
print " $rxA && $rxB &&\n $rxAB\n -took: ", timestr(timediff($t1, $t0)), "\n\n";
}
Выход
Checking string: ' xaaaaaaa term2ater '
-------------
Found possible candidates (A && B)
No (A|B) .* (?!\1)(A|B) terms found!
Bench
(?-xism:term) && (?-xism:m2a)
-took: 1.46875 wallclock secs ( 1.47 usr + 0.00 sys = 1.47 CPU)
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 3.3748 wallclock secs ( 3.34 usr + 0.00 sys = 3.34 CPU)
(?-xism:term) && (?-xism:m2a) &&
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 5.0623 wallclock secs ( 5.06 usr + 0.00 sys = 5.06 CPU)
Checking string: ' xaaaaaaa term2aterm '
-------------
Found possible candidates (A && B)
Found non-overlaped terms: 'm2a' 'term'
Bench
(?-xism:term) && (?-xism:m2a)
-took: 1.48403 wallclock secs ( 1.49 usr + 0.00 sys = 1.49 CPU)
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 3.89044 wallclock secs ( 3.89 usr + 0.00 sys = 3.89 CPU)
(?-xism:term) && (?-xism:m2a) &&
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 5.40607 wallclock secs ( 5.38 usr + 0.00 sys = 5.38 CPU)
Checking string: ' xaaaaaaa ter2ater '
-------------
No (A|B) .* (?!\1)(A|B) terms found!
Bench
(?-xism:term) && (?-xism:m2a)
-took: 0.765321 wallclock secs ( 0.77 usr + 0.00 sys = 0.77 CPU)
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 1.29674 wallclock secs ( 1.30 usr + 0.00 sys = 1.30 CPU)
(?-xism:term) && (?-xism:m2a) &&
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 0.874842 wallclock secs ( 0.88 usr + 0.00 sys = 0.88 CPU)
Checking string: ' Aaa term2ater x x x x x x x x x x x x x'
-------------
Found possible candidates (A && B)
No (A|B) .* (?!\1)(A|B) terms found!
Bench
(?-xism:term) && (?-xism:m2a)
-took: 1.46842 wallclock secs ( 1.47 usr + 0.00 sys = 1.47 CPU)
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 28.078 wallclock secs (28.08 usr + 0.00 sys = 28.08 CPU)
(?-xism:term) && (?-xism:m2a) &&
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 29.4531 wallclock secs (29.45 usr + 0.00 sys = 29.45 CPU)
Checking string: ' Baa term x x x x x x x x x x x x x'
-------------
No (A|B) .* (?!\1)(A|B) terms found!
Bench
(?-xism:term) && (?-xism:m2a)
-took: 1.68716 wallclock secs ( 1.69 usr + 0.00 sys = 1.69 CPU)
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 15.1563 wallclock secs (15.16 usr + 0.00 sys = 15.16 CPU)
(?-xism:term) && (?-xism:m2a) &&
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 1.64033 wallclock secs ( 1.64 usr + 0.00 sys = 1.64 CPU)
Checking string: ' Caa m2a x x x x x x x x x x x x x'
-------------
Found possible candidates (A && B)
Found non-overlaped terms: 'm2a' 'term'
Bench
(?-xism:term) && (?-xism:m2a)
-took: 1.62448 wallclock secs ( 1.63 usr + 0.00 sys = 1.63 CPU)
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 3.0154 wallclock secs ( 3.02 usr + 0.00 sys = 3.02 CPU)
(?-xism:term) && (?-xism:m2a) &&
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 4.56226 wallclock secs ( 4.56 usr + 0.00 sys = 4.56 CPU)
Checking string: ' Daa term2a x x x x x x x x x x x '
-------------
Found possible candidates (A && B)
Found non-overlaped terms: 'm2a' 'term'
Bench
(?-xism:term) && (?-xism:m2a)
-took: 1.45252 wallclock secs ( 1.45 usr + 0.00 sys = 1.45 CPU)
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 16.1404 wallclock secs (16.14 usr + 0.00 sys = 16.14 CPU)
(?-xism:term) && (?-xism:m2a) &&
(?x-ism: (term|m2a) .* (?!\1)(?:term|m2a) )
-took: 17.6719 wallclock secs (17.67 usr + 0.00 sys = 17.67 CPU)