Как заставить регулярное выражение начинаться с начала строки - PullRequest
4 голосов
/ 03 января 2011

Это странная проблема, с которой я столкнулся (и, вероятно, видел ее раньше, но никогда не обращал на нее внимания).

Вот суть кода:

my $url = 'http://twitter.com/' . $handle;
my $page = get($url);

if($page =~ m/Web<\/span>\s*<a href=\"(.+?)\"/gi) {
    $website = $1;
}

if($page =~ m/follower_count\" class=\"stats_count numeric\">(.+?)\s*</g) {
    $num_followers = $1;
}

Он получает URL-адрес в твиттере и делает регулярные выражения, чтобы захватить количество подписчиков и веб-сайт пользователя. Этот код на самом деле работает нормально. Но когда вы переключаете заказ и ищете веб-сайт ПОСЛЕ того, как вы ищете подписчика, веб-сайт становится пустым. Как выясняется, когда вы проверяете строку, кажется, что она сохраняет местоположение того места, где было найдено последнее совпадение. В html число фолловеров появляется после отображения веб-сайта. Если вы сначала выполняете регулярное выражение для количества подписчиков, это похоже на запуск регулярного выражения веб-сайта, на котором счетчик подписчиков прекращается (как индексная ссылка на строку).

Что меня озадачило, так это то, что в конце у меня есть оператор «g», означающий «глобальный», как в «искать строку глобально ... с начала».

Я что-то здесь упускаю? Я не могу понять, почему она возобновляет последнюю позицию регулярного выражения в строке (если это имеет смысл).

Ответы [ 4 ]

13 голосов
/ 03 января 2011

Модификатор /g в скалярном контексте не делает то, что вы думаете.Избавьтесь от этого.

Как объясняет perlretut , /g в скалярных контекстных циклах по каждому совпадению по очереди.Он предназначен для использования в цикле, например:

while ($str =~ /pattern/g) {
    # match on each occurence of 'pattern' in $str in turn
}

Другой способ использования /g находится в контексте списка:

my @results = $str =~ /pattern/g; # collect each occurence of 'pattern' within $str into @results

Если вы используете /gв скалярном контексте, и вы не перебираете его, вы почти наверняка не используете его правильно.

5 голосов
/ 03 января 2011

В кавычках perlop на Regexp Цитировать похожие операторы :

В скалярном контексте каждое выполнение m//g находит следующее совпадение, возвращая true, если оно совпадает, и falseесли больше нет совпадений.Положение после последнего совпадения можно прочитать или установить с помощью функции pos();см поз .Неудачное совпадение обычно сбрасывает позицию поиска в начало строки, но этого можно избежать, добавив модификатор /c (например, m//gc).Изменение целевой строки также сбрасывает позицию поиска.

Таким образом, в скалярном контексте (который вы используете), /g не означает «поиск с начала», это означает «поиск, начинающийся сстрока pos ".«Поиск с начала» используется по умолчанию (без /g).

/g обычно используется, когда вы хотите найти все совпадения для регулярного выражения в строке вместотолько первый матч.В контексте списка он делает это, возвращая список всех совпадений.В скалярном контексте он делает это, начиная поиск с того места, где остановился предыдущий поиск (обычно это делается в цикле).

3 голосов
/ 03 января 2011

Суть в том, что совпадения, выполненные с помощью / g, сохраняют позицию последнего совпадения, так что при следующем сопоставлении этой строки регулярное выражение будет начинаться оттуда.В скалярном контексте это обычно делается для получения нескольких последовательных совпадений в цикле while;В контексте списка / g возвращает все совпадающие (но не перекрывающиеся) результаты.Вы можете узнать больше об этом на perlretut , в разделе Global Matching и на perlop , в разделе Regexp-Quote-Like-Operators.

Вы можете увидеть текущую позициюс функцией pos .Вы также можете установить позицию, используя pos в качестве lvalue: pos($string) = 0; сбросит позицию до начала строки.

Нет особых причин использовать / g в скалярном контексте вне цикла, поскольку вы можете получить точно такую ​​же функциональность, используя утверждение \ G.

.. конечно, тогда никто не помнит, как работает \ G, и вы вернулись на круги своя, но это уже другая тема.

0 голосов
/ 03 января 2011

m // g не сбрасывает позицию.Вы должны сделать это вручную.См. Это для справки: http://perldoc.perl.org/functions/pos.html

Я полагаю, вы просто установили pos на 0 или undef, и это будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...