несколько регулярных выражений с использованием Perl

Привет, этот сайт уже несколько раз помогал мне решать мои проблемы в Perl. это первый раз, когда мне приходится задавать вопрос, потому что я не могу найти ответ ни в Google, ни в переполнении стека.

То, что я пытаюсь сделать, это получить содержимое между двумя словами. Но шаблоны, которым они должны соответствовать, меняются. Я пытаюсь получить информацию о продукте. Марка, описание, название и так далее. Я пытался сопоставить регулярное выражение за другим, но, к сожалению, это не работает, потому что $1 остается определенным. Попытка отменить определение переменной $1 дает мне сообщение об ошибке «только для чтения», что логично. Я опубликую свой код ниже, возможно, у кого-то есть идея, как заставить его работать.

#!/usr/bin/perl
use strict;
use warnings;
use LWP::Simple;
use IO::File;
use utf8;
my $nfh = IO::File->new('test.html','w');
my $site = 'http://www.test.de/dp/';
my $sku = '1550043196';
my $url = join('',$site,$sku);
my $content = get $url;
my $name = $1 if ($content =~ m{<span id="productTitle" class="a-size-large">(.*?)</span>}gism);
print "$name\n";

# My attempt of undefying 
#undef $1;

my $marke = $1 if ($content =~ m{data-brand="(.*?)"}gism);
print "$marke\n";

Какие-либо предложения?


person Lehmann    schedule 19.02.2015    source источник
comment
Не могли бы вы предоставить образец ввода вместе с ожидаемым результатом?   -  person Avinash Raj    schedule 19.02.2015
comment
Примечание: my ($marke) = $content =~ m{data-brand="(.*?)"}gism; лучше, чем my $marke = $1 if ($content =~ m{data-brand="(.*?)"}gism);   -  person mpapec    schedule 19.02.2015


Ответы (1)


Во-первых, никогда не используйте конструкцию типа:

my $var = $val if( $some );

согласно документации:

ПРИМЕЧАНИЕ. Поведение my, state или our изменено с помощью условного модификатора оператора или конструкции цикла ( например, my $x if ... ) не определено. Значение переменной my может быть undef, любым ранее присвоенным значением или любым другим. Не полагайтесь на это. Будущие версии Perl могут делать что-то отличное от той версии Perl, на которой вы ее пробуете. Вот драконы.

Оператор m//, когда модификатор /g указан в контексте списка, возвращает список подстрок, соответствующих любым захватывающим скобкам в регулярном выражении. Итак, как говорит @Сухой27 в комментарии выше, вы должны использовать:

my ($some) = $str =~ m/...(...).../g;

На простом примере:

use strict;
use warnings;

my $u="undefined";
my $str = q{some="string" another="one"};

#will match
my ($m1) = $str =~ m/some="(.*?)"/g;
print 'm1=', $m1 // $u, '= $1=', $1 // $u, "=\n";

#will NOT match
my ($m2) = $str =~ m/nothere="(.*?)"/g;
print 'm2=', $m2 // $u, '= $1=', $1 // $u, "=\n";

#will match another
my ($m3) = $str =~ m/another="(.*?)"/g;
print 'm3=', $m3 // $u, '= $1=', $1 // $u, "=\n";

печатает:

m1=string= $1=string=
m2=undefined= $1=string=   #the $1 hold previously matched value
m3=one= $1=one=

Как видите, $1 остается, если сопоставление НЕ успешно. В документации говорится:

Эти специальные переменные, такие как хэш %+ и пронумерованные переменные совпадения ($1, $2, $3 и т. д.), динамически контролируются до конца окружающего блока или до следующего успешного совпадения, в зависимости от того, что наступит раньше. (См. Составные операторы в perlsyn.)

ПРИМЕЧАНИЕ. Неудачные совпадения в Perl не сбрасывают переменные сопоставления, что упрощает написание кода, который проверяет ряд более конкретных случаев и запоминает наилучшее совпадение.

Итак, если вы не хотите определять $1, вы можете заключить соответствующую часть в блок, например:

use strict
use warnings;

my $u="undefined";
my $str = q{some="string" another="one"};
my($m1,$m2,$m3);

{($m1) = $str =~ m/some="(.*?)"/g;}
print 'm1=', $m1 // $u, '= $1=', $1 // $u, "=\n";

{($m2) = $str =~ m/nothere="(.*?)"/g;}
print 'm2=', $m2 // $u, '= $1=', $1 // $u, "=\n";

{($m3) = $str =~ m/another="(.*?)"/g;}
print 'm3=', $m3 // $u, '= $1=', $1 // $u, "=\n";

что печатает

m1=string= $1=undefined=
m2=undefined= $1=undefined=
m3=one= $1=undefined=

PS: я не гуру Perl, возможно, другие дополнят/исправят этот ответ.

person jm666    schedule 19.02.2015