Ошибки в 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.