Просмотр сообщений

В этом разделе можно просмотреть все сообщения, сделанные этим пользователем.


Сообщения - Serg31416

Страницы: [1] 2
1
Привет.

 Использую Perl 5.10.2, получаю:

\'a\' =~ /^(?(?=b)b)a$/       # not match...

Очень интересно, такое впечатление, что yes-subpattern пробуется на соответствие, хотя условие (?=b) должно возвращать false.

2
Народ, который занимается разработкой Перла, окончательно признал, что "This *is* a bug. An optimization bug probably. In the PLUS regop." И вот интересный пример такого человека, который написал вышеприведённые слова: заменим \\w+ на (?:\\w|z)+ и потом на (?:\\w|zz)+, получим разный вывод:

\'ab\' =~ /(((?:\\w|z)+)(?{print defined $2 ? "\\$2=$2\\n" : "\\$2 not defined\\n"})){2}/;

$2=ab
$2 not defined
$2=b

\'ab\' =~ /(((?:\\w|zz)+)(?{print defined $2 ? "\\$2=$2\\n" : "\\$2 not defined\\n"})){2}/;

$2=ab
$2=a
$2=b

Кстати, я на днях засабмитил ещё один багрепорт, связанный с неправильной работой операторов \\L, \\l, \\U и \\u. Эти операторы в отличие от функций lc, lcfirst, uc и ucfirst выполняются слева направо:

print "\\L\\udD\\n";     # Dd верно
print "\\LdD\\udD\\n";   # dddd уже неверно!

А если рядом поставить \\U и \\L (4 комбинации, то вообще будет кошмар: ошибка синтаксиса:

print "\\U\\La\\n";

3
Извините, почему-то исправляется не последнее, а предпоследнее моё сообщение, а потом форум не даёт его редактировать, поэтому оно раздвоилось.
========================================

Я над этим серьёзно ещё не думал, а сейчас подумал раза 2 и считаю, что это всё-таки ошибка. Поспешил я со 2-м письмом в perl.org, ладно, посмотрим, что завтра-послезавтра оттуда ответят.
Вот мой разбор работы этого re, как я понимаю этот механизм.
Итак, имеем минимальный пример с подобной ошибкой:
\'ab\' =~ /((\\w+)(?{print defined $2 ? "\\$2=$2\\n" : "\\$2 not defined\\n"})){2}/;
Оно выводит:
$2=ab
$2 not defined
$2=b
Проблема: почему $2 not defined? Ведь мы визуально только что перед этим выводом закрыли 2-ю скобку и должны получить $2 (а также $+, $^N и \\2 определёнными, т.к. 2-я пара скобок только что участвовала в совпадении. А они все неопределённые. Что-то не то...
Я подозреваю, что возможная ошибка возникла от того, что нумерованные переменные (и вообще спец. переменные re) локализуются не только при входе в каждый блок программы (т.е. имеют структуру стека)), но и внутри re, а это неправильно.
При об-ке этого re оно должно как бы раскручиваться: аналогично тому, как \\w{2} эквивалентно \\w\\w, так и всё re эквивалентно
((\\w+)({print ...})((\\w+)({print ...})
Но при этом во 2-м экз. скобки нумеруются тоже 1 и 2 и порождают $1 и $2.
Вначале 1-е \\w+ захватит всё ab и на печать выйдет $2=ab.
Затем входим во 2-й экз. re и когда входим во 2-1 экз. 2-й скобки, $2 получает значение undefined. Видим, что \\w не совпадает. Не беда, у нас есть сохр. состояние, возвращаемся к 1-му экз. 2-й скобки. Но при возврате мы входим справа в 1-й экз. 2-й пары скобок, поэтому $2 опять получает значение undefined, которое наслаивается на предыдущее, а это неправильно. Квантификатор + отдаёт 1 букву, мы захватываем 1-м экз. 2-й пары скобок символ a, затем выходим за скобку. Тут надо сформировать $2 и т.д., но, видимо, здесь механизм об-ки re видит, что $2 уже имеет значение, поэтому вместо этого отменяется предыдущее значение undefined для $2, в результате $2 опять получает значение undefined, что и выводится, а надо вывести a.
Вот так мне кажется...

===

Я ещё поумал и вижу, что я ошибался: когда \\w+ отдаёт символ b, то мы
не заходим левее открывающей скобки в выражении (\\w+), поэтому $2 остаётся неопределённым, что и печатается.

===

Опа, я через неск. часов после этого опять раза 2 подумал и пришёл к выводу, что $2=undefined интуитивно должно быть ошибочно, правильно всё-таки выводить $2=a, как я раньше писал.
Проверил почту - вот это да, пришёл ответ от гуру рег. выражений Дж. Фридла, который живёт на regex.info. (В сети есть 3-е издание его книги "Регулярные выражения"). Он написал:

Hi Serge,
I\'ve been thinking about this for a while, and as far as I can tell it does seem
to be a bug. By definition, $2 must be defined before the (?{...}) can run.

It\'s probably a problem with how it backtracks. I\'d suggest filing a bug report..

Поначалу я раздвоил это выражение ввиду квантификатора {2}, получилось такое:

((\\w+)(?{print...}))((\\w+)(?{print...}))

(Здесь имеем в виду, что вторая копия также производит $1 и $2). Но так рассуждать неправильно, реально ничего не раздваивается.
Вот почему выводится $2=undefined, по моему мнению:
вначале (\\w+) захватывает всё и выводится, что $2=ab.
Далее выходим на модификатор {2}. Текущая позиция отмечена через |:
(\\w+)) | {2}
Видим, что повтор \\w не совпадает. Делаем бэктрекинг и по пути входим справа за закрывающую скобку:
(\\w+ | )
Видимо, в этом случае движок делает $2 undefined, а почему? Интуитивно кажется, что это надо делать только, когда мы выходим левее соответствующей открывающей скобки.
Но я сомневаюсь, что авторы движка станут это исправлять: это вопрос идеологии работы движка, и ведь тогда теоретически некоторые старые программы могут начать не так работать...

4
Там немного не так надо было выводить, а то не видно различий между undefined и null. Вот минимальный пример:

#!perl -w
use strict;
#use re qw(debug);

print "Match: \\$1=$1 \\$2=$2" if \'ab\' =~
/^((\\w+)
    (?{print defined $2 ? "\\$2=$2\\n" : "\\$2 not defined\\n"})
  ){2}$
/x;

Выводит:
$2=ab
$2 not defined
$2=b
Match: $1=b $2=b

Если включить use re qw(debug), то видно, что 2-я пара скобок открывается и закрывается перед буквой b. В этом случае должны создаваться переменные $2, $+, $^N и обр. ссылка \\2 с определёнными значениями, а они все неопределены. Я написал на ...@perl.org, пусть разъяснят.
Хм, вроде я понял, ошибок тут, похоже, нет, зря гуру беспокоил...
 Undefined выводится, когда предыдущий захват 2-й парой скобок откачен, а нового захвата ещё не было. Хотя в re мы находимся за 2-й парой скобок. Вот так ставить квантификаторы к захватывающим скобкам... ;-\\

===

Я ещё поумал и вижу, что я ошибался: когда \\w+ отдаёт символ b, то мы
не заходим левее открывающей скобки в выражении (\\w+), поэтому $2 остаётся неопределённым, что и печатается.

===

Опа, я через неск. часов после этого опять раза 2 подумал и пришёл к выводу, что $2=undefined интуитивно должно быть ошибочно, правильно всё-таки выводить $2=a, как я раньше писал.
Проверил почту - вот это да, пришёл ответ от гуру рег. выражений Дж. Фридла, который живёт на regex.info. (В сети есть 3-е издание его книги "Регулярные выражения"). Он написал:

Hi Serge,
I\'ve been thinking about this for a while, and as far as I can tell it does seem
to be a bug. By definition, $2 must be defined before the (?{...}) can run.

It\'s probably a problem with how it backtracks. I\'d suggest filing a bug report..

Поначалу я раздвоил это выражение ввиду квантификатора {2}, получилось такое:

((\\w+)(?{print...}))((\\w+)(?{print...}))

(Здесь имеем в виду, что вторая копия также производит $1 и $2). Но так рассуждать неправильно, реально ничего не раздваивается.
Вот почему выводится $2=undefined, по моему мнению:
вначале (\\w+) захватывает всё и выводится, что $2=ab.
Далее выходим на модификатор {2}. Текущая позиция отмечена через |:
(\\w+)) | {2}
Видим, что повтор \\w не совпадает. Делаем бэктрекинг и по пути входим справа за закрывающую скобку:
(\\w+ | )
Видимо, в этом случае движок делает $2 undefined, а почему? Интуитивно кажется, что это надо делать только, когда мы выходим левее соответствующей открывающей скобки.
Но я сомневаюсь, что авторы движка станут это исправлять: это вопрос идеологии работы движка, и ведь тогда теоретически некоторые старые программы могут начать не так работать...

5
print "Match: \\$1=$1" if \'abcde\' =~ /^((\\w\\w+)(?{print defined $2 ? "-$2-\\n" : "--\\n"})){2}$/;

Выводит:

-abcde-
--
--
-de-
Match: $1=de

Объясните, почему 2 раза $2 оказался undefined, ведь после выхода за 2-ю захватывающую скобку в $2 должно быть минимум 2 символа.

Сергей

6
Привет.

 Можно ли регулярным выражением Perl проверить синтаксис арифметического выражения типа -(+1+2)*(3/(1-2))/((-3))? Народ в этом сомневается и использует для этого модуль Perl. Я сегодня подумал раза 2 и получил легко и красиво такое выражение. Потом написал об этом статейку Perl регулярные выражения: проверка правильности арифметического выражения
 Возможно, что до меня ещё никто не получал такого регулярного выражения Perl. Думаю, что посетителям этой ветки форума это будет интересно.

7
Привет.

Вчера неожиданно обнаружил ошибку в ActiveState Perl 5.10 в регулярных выражениях. Написал об этом тут:
http://forums.webscript.ru/showthread.php?s=&threadid=27405

8
Perl / Ошибка в ActiveState Perl 5.10.0
« : 16 Октября 2010, 11:19:57 »
Привет.

 Вчера в ActiveState Perl 5.10.0 build 1003 для Win 32 нашёл ошибку в регулярных выражениях: конструкции (?=) и (?<=) вообще не работают! Нигде не находится пустой фрагмент текста при заглядывании впёрёд и назад! Напр., оператор
\'aaa\' =~ /a(?=)aa/;
не находит соответствия!
Только что скачал ActiveState Perl 5.12, проверил и увидел, что эта ошибка исправлена. Ведь при заглядывании вперёд и назад пустой фрагмент должен находиться везде, даже перед \\A и после \\z в пустой строке.
Интересно, как с этой ошибкой обстоит дело в других платформах? Откуда эта ошибка могла взяться, ведь в предыдущих версиях её не было. ActiveState по идее просто портирует этот модуль работы с регекспами под Виндовс. Неужели, эта ошибка возникла в ядре Перла?

9
Привет.

 Я начал публиковать продвинутые статьи по регулярным выражениям Perl  по главам своей книги "Perl для профессиональных программистов. Регулярные выражения".
 Также буду публиковать полезные программки на Perl, интересные статьи для веб-мастеров и отвечать на вопросы по Perl re. Заходите, кому интересно.

10
Со ссылок к статьям идет редирект на корень сайта

11
Perl / Ещё одна ошибка в Perl re
« : 07 Июля 2008, 10:17:48 »
Нашёл ещё одну ошибку в Perl re:

print "Match" if \'ab\' =~ /^a?(?=b)b/;

не находит, а должен бы. ^ можно заменить на \\A, а ? можно заменить на * с тем же результатом.
Это я уже засабмитил на http://bugs.activestate.com/show_bug.cgi?id=78536
 Вот ещё сходные ошибки:

print $& if \'ab\' =~ /a?(?=b)b/;
print $& if \'ab\' =~ /a*(?=b)b/;

печатают b, а должны печатать ab.
 Похоже, что эта ошибка есть во всех версиях и платформах. По крайней мере, в
ActiveState Perl 5.10.0 под Win32 и в 5.8.8 под Debian она есть.
 Мой e-mail cron+c [] cronc.com

12
Привет.

 Один программист поставил такую задачку, которая встречается при обработке ini-файлов в связи с изменением версии программы.
Написать оператор подстановки s///, который в тексте во всех строках, где не встречается aaa, заменит все подстроки bbb на ccc. В общем случае эти образцы подстрок находятся в переменных $a, $b и $c.

Например, имеем фрагмент программы:

$_=<bbb aaa bbb
bbb aa bbb bbb
aaa bbb bbb
aa bbb bbb
EOD

s/.../.../;
print $_;

 При выводе должно получиться

bbb aaa bbb
ccc aa ccc ccc
aaa bbb bbb
aa ccc ccc

 Аналогично, написать оператор s///, который заменит все bbb на ccc во всех строках, в которых встречается aaa.

13
Регулярные выражения / Книжка по gegexp
« : 04 Марта 2008, 12:53:40 »
Более подробно, нет ошибок, исправлены его ошибки.

14
Регулярные выражения / Книжка по gegexp
« : 28 Февраля 2008, 09:20:03 »
Привет всем.

 Для тех, кто интересуется рег. выражениями: вышла моя книжка "Профессиональная работа в Perl. Регулярные выражения".
Я в ней глубоко и подробно разбираю этот вопрос. Юникод не рассматриваю. Вот один мой пример из этой книги:

# Заменить во всем тексте все символы табуляции соответствующим числом пробелов.

$_=<a\\tПервая строка\\t.
Вторая строка.
\\t\\tТретья строка.
Четвертая строка.
EOF

my ($offs,$tmp);

s/(?:^(?{ $offs=0 }))?
  ([^\\t\\n]*)
  \\t
 /$tmp=$offs+length $1;
  $offs+=$tmp+(8-$tmp % 8);
  $1.\' \' x (8-$tmp % 8)/egmx;

print $_;
 
 
 На books.ru эта книжка стоит 225 р., я могу продать из своих авторских экз. за 200 р. вместе с пересылкой
(WMR, Яндекс-деньги, сберкасса). Пишите на wait4sleep [] rambler . ru

15
Perl / вопрос по регекспам
« : 25 Декабря 2006, 19:19:56 »
Привет.

 Вот так, наверно...

$_=\' ddd

aaa
 \';
s#<(?!(?:img|p|br))\\b[^>]*>##gi;
print;