Ваши выражения не эквивалентны
Этот:
$string=~s/^.+\///;
$string=~s/\.shtml//;
заменяет текст .shtml
и все до последней косой черты включительно.
Этот:
$string=~s/(^.+\/|\.shtml)//;
заменяет либо текст .shtml
или все до последней косой черты включительно.
Это одна из проблем объединения регулярных выражений: одно сложное регулярное выражение сложнее написать, сложнее понять и сложнее отладить, чем несколько простых.
Наверное, неважно, что быстрее
Даже если ваши выражения были эквивалентны, использование одного или другого, вероятно, не оказало бы существенного влияния на скорость вашей программы. Операции в памяти, такие как s///
, выполняются значительно быстрее, чем файловый ввод-вывод, и вы указали, что выполняете много файлового ввода-вывода.
Вы должны профилировать свое приложение с помощью чего-то вроде Devel::NYTProf, чтобы увидеть, действительно ли эти конкретные замены узкое место (я сомневаюсь, что они есть). Не тратьте время на оптимизацию того, что уже работает быстро.
Чередования мешают оптимизатору
Имейте в виду, что вы сравниваете яблоки и апельсины, но если вас все еще интересует производительность, вы можете посмотреть, как perl оценивает конкретное регулярное выражение, используя тег re
прагма:
$ perl -Mre=debug -e'$_ = "foobar"; s/^.+\///; s/\.shtml//;'
...
Guessing start of match in sv for REx "^.+/" against "foobar"
Did not find floating substr "/"...
Match rejected by optimizer
Guessing start of match in sv for REx "\.shtml" against "foobar"
Did not find anchored substr ".shtml"...
Match rejected by optimizer
Freeing REx: "^.+/"
Freeing REx: "\.shtml"
Механизм регулярных выражений имеет оптимизатор. Оптимизатор ищет подстроки, которые должны появляться в целевой строке; если эти подстроки не могут быть найдены, совпадение немедленно завершается ошибкой, без проверки других частей регулярного выражения.
С /^.+\//
оптимизатор знает, что $string
должен содержать хотя бы одну косую черту для соответствия; когда он не находит косых черт, он немедленно отклоняет совпадение, не вызывая полный механизм регулярных выражений. Аналогичная оптимизация происходит с /\.shtml/
.
Вот что делает Perl с комбинированным регулярным выражением:
$ perl -Mre=debug -e'$_ = "foobar"; s/(?:^.+\/|\.shtml)//;'
...
Matching REx "(?:^.+/|\.shtml)" against "foobar"
0 <> <foobar> | 1:BRANCH(7)
0 <> <foobar> | 2: BOL(3)
0 <> <foobar> | 3: PLUS(5)
REG_ANY can match 6 times out of 2147483647...
failed...
0 <> <foobar> | 7:BRANCH(11)
0 <> <foobar> | 8: EXACT <.shtml>(12)
failed...
BRANCH failed...
1 <f> <oobar> | 1:BRANCH(7)
1 <f> <oobar> | 2: BOL(3)
failed...
1 <f> <oobar> | 7:BRANCH(11)
1 <f> <oobar> | 8: EXACT <.shtml>(12)
failed...
BRANCH failed...
2 <fo> <obar> | 1:BRANCH(7)
2 <fo> <obar> | 2: BOL(3)
failed...
2 <fo> <obar> | 7:BRANCH(11)
2 <fo> <obar> | 8: EXACT <.shtml>(12)
failed...
BRANCH failed...
3 <foo> <bar> | 1:BRANCH(7)
3 <foo> <bar> | 2: BOL(3)
failed...
3 <foo> <bar> | 7:BRANCH(11)
3 <foo> <bar> | 8: EXACT <.shtml>(12)
failed...
BRANCH failed...
4 <foob> <ar> | 1:BRANCH(7)
4 <foob> <ar> | 2: BOL(3)
failed...
4 <foob> <ar> | 7:BRANCH(11)
4 <foob> <ar> | 8: EXACT <.shtml>(12)
failed...
BRANCH failed...
5 <fooba> <r> | 1:BRANCH(7)
5 <fooba> <r> | 2: BOL(3)
failed...
5 <fooba> <r> | 7:BRANCH(11)
5 <fooba> <r> | 8: EXACT <.shtml>(12)
failed...
BRANCH failed...
Match failed
Freeing REx: "(?:^.+/|\.shtml)"
Обратите внимание, насколько длиннее вывод. Из-за чередования оптимизатор не срабатывает и выполняется полный движок регулярных выражений. В худшем случае (нет совпадений) каждая часть чередования проверяется на соответствие каждому символу в строке. Это не очень эффективно.
Итак, чередования медленнее, верно? Нет потому что...
Это зависит от ваших данных
Опять же, мы сравниваем яблоки и апельсины, но с:
$string = 'a/really_long_string';
комбинированное регулярное выражение на самом деле может быть быстрее, потому что с s/\.shtml//
оптимизатору приходится сканировать большую часть строки, прежде чем отклонить совпадение, в то время как комбинированное регулярное выражение сопоставляется быстро.
Вы можете тестировать это для развлечения, но по сути это бессмысленно, поскольку вы сравниваете разные вещи.
person
ThisSuitIsBlackNot
schedule
13.04.2016
foo/bar.shtml
вbar
; ваша версия превращает его вbar.shtml
- person ThisSuitIsBlackNot   schedule 14.04.2016