Почему так? Perl
От: Аноним  
Дата: 20.09.06 14:06
Оценка:
Есть текст, в котором нужно выделить все совпадения с вот таким шаблоном "aaa(.+?)bbb(.+?)ccc" и распечатать $1/$2 соответственно. Так вот почему если сделать так:

   @Links = $TMP=~/aaa(.+?)bbb(.+?)ccc/g;
   join("\n",@Links);


то всё нормально, а если сразу, без перехода к массиву, т.е. вот так:

   foreach ($TMP=~/aaa(.+?)bbb(.+?)ccc/g)
   {
     print $1."\n".$2."\n";
   }


то распечатается одно и тоже (последнее) совпадение с шаблоном столько раз, сколько совпадение найдено.
Я понимаю, что в случае foreach, видимо, каждый раз выполняется сопоставление и печатается одно и тоже, но не пойму логику работы перла в случае перехода к массиву. Ведь модификатор /g есть и там и там..
Re: Почему так? Perl
От: Alex Kirhenshtein Латвия http://www.netxms.org
Дата: 20.09.06 15:56
Оценка: 3 (1)
Здравствуйте, <Аноним>, Вы писали:

А>
А>   foreach ($TMP=~/aaa(.+?)bbb(.+?)ccc/g)
А>   {
А>     print $1."\n".$2."\n";
А>   }
А>


1) (m//) вернет list
2) по результатам работы m// будут выставлены $1 и $2 — в последний матч
3) foreach распечатает их столько раз, сколько будет элементов листе — по количеству матчей.

Используйте $_ или замените foreach на while.

perlsyn:

LABEL foreach VAR (LIST) BLOCK
...
The "foreach" loop iterates over a normal list value and sets the vari-
able VAR to be each element of the list in turn.
...
"for" comes more naturally.) If VAR is omitted, "$_" is set to each
value.

NetXMS: Open Source Network monitoring solution
Re: Почему так? Perl
От: kinoman http://pseudo-tech-notes.blogspot.com/
Дата: 20.09.06 16:36
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Есть текст, в котором нужно выделить все совпадения с вот таким шаблоном "aaa(.+?)bbb(.+?)ccc" и распечатать $1/$2 соответственно. Так вот почему если сделать так:


А>
А>   @Links = $TMP=~/aaa(.+?)bbb(.+?)ccc/g;
А>   join("\n",@Links);
А>


А>то всё нормально, а если сразу, без перехода к массиву, т.е. вот так:


А>
А>   foreach ($TMP=~/aaa(.+?)bbb(.+?)ccc/g)
А>   {
А>     print $1."\n".$2."\n";
А>   }
А>


А>то распечатается одно и тоже (последнее) совпадение с шаблоном столько раз, сколько совпадение найдено.

А>Я понимаю, что в случае foreach, видимо, каждый раз выполняется сопоставление и печатается одно и тоже, но не пойму логику работы перла в случае перехода к массиву. Ведь модификатор /g есть и там и там..

Второй вариант(скалярный контекст) надо писать так:

while ($TMP=~/aaa(.+?)bbb(.+?)ccc/g)
{
     print $1."\n".$2."\n";
}


В случае foreach (...) мы вроде ожидаем контекст массива. Поэтому мы сразу получаем массив и естественно что в $1 и $2 результаты последнего совпадения — их мы и печатаем каждый раз.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.