|
|
ru.perl- RU.PERL ---------------------------------------------------------------------- From : Artem Chuprina 2:5020/400 03 Mar 2008 15:50:14 To : Alexander V. Gaiduk Subject : Re: баг Перла или баг мозга? -------------------------------------------------------------------------------- Alexander V. Gaiduk @ Mon, 3 Mar 2008 09:12:38 +0000 (UTC): AVG> доброго времени суток. AVG> пописывая на выходных свою парсилку натолкнулся на один AVG> очень прикольный глюк. с одной стороны похоже на баг Перла, AVG> с другой неправомерное использование спискового контекста AVG> совместно с регулярными выражениями. AVG> кароче, я добился 100% повторяемости этого глюка, AVG> вот исходник: AVG> --8<------------------------------------------------------------- AVG> #!/usr/bin/perl -w AVG> use strict; AVG> my $page = q{ AVG> <gg> AVG> <xx>x01</xx> AVG> <px> AVG> <pp>p11</pp> AVG> <pp>p12</pp> AVG> <pp>p13</pp> AVG> </px> AVG> <zz>z01</zz> AVG> </gg> AVG> <gg> AVG> <xx>x01</xx> AVG> <px> AVG> <pp>p21</pp> AVG> <pp>p22</pp> AVG> <pp>p23</pp> AVG> <px> AVG> <zz>z02</zz> AVG> </gg> AVG> <gg> AVG> <xx>x01</xx> AVG> <px> AVG> <pp>p31</pp> AVG> <pp>p32</pp> AVG> <pp>p33</pp> AVG> <px> AVG> <zz>z03</zz> AVG> </gg> AVG> }; AVG> foreach my $g ($page =~ m!<gg>(.+?)</gg>!sg) { AVG> my $xx = $1 if ($g =~ m!<xx>(.+?)</xx>!sg); AVG> my $zz = $1 if ($g =~ m!<zz>(.+?)</zz>!sg); # ** AVG> # my $g = $g; AVG> my $pp = ''; AVG> foreach my $p ($g =~ m!<pp>(.+?)</pp>!sg) { $pp .= "($p)"; } AVG> print "ZZ: $zz\n"; AVG> print "XX: $xx\n"; AVG> print "PP: $pp\n"; AVG> } AVG> --8<------------------------------------------------------------- AVG> 1. если раскоментировать фрагмент "my $g = $g;" - работает правильно. AVG> 2. если в регэкспе (помеченом **) убрать модификатор "g" AVG> работает правильно. AVG> 3. если в данных блок "<zz>...</zz>" поднять над блоком <px>...<.px> AVG> работает правильно. AVG> в текущей версии работает неправильно. AVG> у кого какие соображения будут по этому поводу? В скалярном контексте модификатор /g оставляет в строке закладку. Следующий заход на ту же строку начнется с того места, где закончился предыдущий. За счет этого работает идиома while ($string =~ /.../g) if, соответственно, задает скалярный контекст. Дальше объяснять? -- Artem Chuprina RFC2822: <ran{}ran.pp.ru> Jabber: ran@jabber.ran.pp.ru When C++ is your hammer, everything looks like a thumb -- Latest seen from Steven M. Haflich, in c.l.l --- ifmail v.2.15dev5.4 * Origin: Leninsky 45 home network (2:5020/400) Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.perl/53241777c9dab.html, оценка из 5, голосов 10
|