Ошибки в Perl и в Perl регулярных выражениях
Я не один раз находил ошибки в Perl особенно в Perl регулярных выражениях. Некоторые из них уже исправили, но одна остаётся и в версии ActiveState Perl 5.10.
print "Match" if 'ab' =~ /^a?(?=b)b/;Оператор m// не находит соответствия, а должен бы. Если убрать подшаблон (?=b), то оператор m// работает верно ^ можно заменить на \A, а ? можно заменить на * с тем же результатом.
Эту ошибку я засабмитил на http://bugs.activestate.com/show_bug.cgi?id=78536. На той странице есть ссылка на страницу сайта perl.org с дискуссией. Вот ещё сходные ошибки:
print $& if 'ab' =~ /a?(?=b)b/; print $& if 'ab' =~ /a*(?=b)b/;печатают b, а должны печатать ab. Исправление этой ошибки, которая проявлялась на всех платформах, потребовало у разработчиков ядра Perl существенной переделки алгоритма работы Perl регулярных выражений.
Несколько лет назад, когда на серверах в Интернете стоял Perl 5.6.1, я нашёл удивительную ошибку и написал такую программку из 19-ти байтов
map{while(1){}}@a;которая завешивала (или зацикливала) интерпретатор Perl при её трансляции (!). Здесь всё дело в том, что оператор while(1) употребляется внутри оператора map. Было такое ощущение, что до меня никто не применял такой цикл... В версии Perl 5.8.5 эта ошибка была устранена (я о ней не сообщал разработчикам).
От этой программки
my $a=qr/(a)/; print "Found!\n" if 'abc' =~ /(??{$a})/;Perl тоже вываливался, но эта ошибка в версии ActiveState Perl 5.10 уже исправлена.
Эта программка зацикливает Perl и в версии 5.10:
print 'OK' if '5XXXXX' =~ /(\d+)(??{ 'X' x \1 })/;Но формально это не ошибка, здесь есть обращение к непонятной ссылке.
До версии Perl 5.10 эта программка
print "\$1=$1, \$^N=$^N, \$+=$+" if 'ab' =~ /(\w)+/;также работала неправильно, значение переменной $^N было неопределённым, тогда как значение переменной $+ оставалось верным.
Вчера, 16.10.2010 г. в ActiveState Perl 5.10.0 build 1003 неожиданно обнаружил грубую ошибку в регулярных выражениях. Конструкция (?=), которая означает "с этого места имеется пустой фрагмент текста" вообще не работает! То же относится к аналогичной конструкции "заглядывания назад" (?<=). Например, не находится соответствие в операторах
'aaa' =~ /a(?=)aa/; 'aaa' =~ /(?=)aaa/; 'aaa' =~ /aaa(?=)/;
и т.д. Я пришёл в недоумение, ведь это работало правильно в ActiveState Perl 5.8.7 и в более ранних версиях, которые были установлены у меня прежде. Только что скачал ActiveState Perl 5.12 и с удовлетворением обнаружил, что это заглядывание вперёд/назад с пустой строкой опять работает верно. Ведь пустая строка находится в любом месте, даже перед метасимволом \A и после \z в пустой строке! Фрагмент кода
print "1" if '' =~ /(?<=)\A(?=)(?<=)\z(?=)/;
выводит 1. Не знаю, как с этой временной ошибкой было в других версиях Perl, ведь механизм регулярных выражений относится к ядру Perl и, очевидно, просто портируется программистами ActiveState под Windows.
Читайте мою новую статью об ошибках в Perl регулярных выражениях Perl 5.12.