Каков правильный синтаксис для использования perl-массива хэшей с регулярным выражением? пример получает гиперссылки со страницы - PullRequest
1 голос
/ 03 сентября 2010
@urls= $field =~ /<a.*?href="(.*?)".*?>.*?<\/a>/mgo; #multi-line, global, compile-once
@text= $field =~ /<a.*?href=".*?".*?>(.*?)<\/a>/mgo;
for ($count=0; $count<(scalar @urls); $count++){
    print "\"".$text[$count]."\" goes to ->\"".$url[$count]."\"\n";}

Каков правильный синтаксис, чтобы сделать его таким же, как предыдущие строки?

(@array_of_links->{"url"}, @array_of_links->{"text"}) = $field =~ /<a.*?href="(.*?)".*?>(.*?)<\/a>/mgo;
for ($count=0; $count<(scalar @array_of_links); $count++){
    print "\"".$array_of_links[$count]{"text"}."\" goes to ->\"".$array_of_links[$count]{"text"}."\"\n";}

Ответы [ 2 ]

2 голосов
/ 03 сентября 2010

Я начну со стандартного заявления об отказе от ответственности за то, что синтаксический анализ HTML с помощью регулярных выражений является плохой идеей.

Оценка соответствия регулярному выражению в скалярном контексте:

В скалярном контексте, каждое выполнение m//g находит следующее совпадение, возвращает true, если оно совпадает, и false, если дальнейшее совпадение отсутствует.

Затем для каждого совпадения push новый хэш-адрес на @array_of_links:

my @array_of_links;
push @array_of_links => { url => $1, text => $2 }
  while $field =~ /<a.*?href="(.*?)".*?>(.*?)<\/a>/mgo;

Ваш код для выгрузки содержимого не очень идиоматичен.Петля for в стиле Perl более понятна и синтаксически менее загромождена:

for (@array_of_links) {
  print qq["$_->{text}" goes to ->"$_->{url}"\n];
}
2 голосов
/ 03 сентября 2010

Я думаю, что вы хотите это:

#!/usr/bin/perl

use strict;
use warnings;

my @array_of_links;

my $field = <<EOS;
<a href="foo.html">foo</a>
<a href="bar.html">bar</a>
<a href="baz.html">baz</a>
EOS

#/ this comment is to unconfuse the SO syntax highlighter. 

while ($field =~ m{<a.*?href="(.*?)".*?>(.*?)</a>}g) {
    push @array_of_links, { url => $1, text => $2 };
}

for my $link (@array_of_links) {
    print qq("$link->{text}" goes to -> "$link->{url}"\n);
}

Модификатор /o regex ничего не делает, если в него не интерполируются никакие строки (и, вероятно, его даже не следует использовать из-за его удивительного поведения),Модификатор /m regex ничего не делает, потому что в вашем регулярном выражении нет якорей ^ или $.

Вы не можете создать массив хэшей таким образом.Возможно, вы захотите перечитать циклы perldoc perldsc.

C-Style for, как правило, не требуются в Perl 5. Итерация цикла for намного лучше.Если вам нужно знать индекс в массиве, вы должны использовать оператор диапазона:

for my $i (0 .. $#array_of_links) {
    print qq($i. "$array_of_links[$i]{text}" goes to -> "$array_of_links[$i]{url}"\n);
}

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

Однако, похоже, вы пытаетесь использовать регулярное выражение для разбора HTML.Это путь, который заполнен болью .Вы действительно должны изучить , как использовать вместо этого анализатор .

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