Perl делает замену в самой замене - PullRequest
0 голосов
/ 03 ноября 2019

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

Вот как я подбираю нужную часть: (class="p_hw"><a href=")(http://[^<>"]*?xxxx\.com\/[^<>"]*[=/])([^<>"]*)(">(?:<b>)?)(.*?)(?=<)

Мне нужно заменить http:// наentry://, за которым следует определенное значение параметра http url ($3 в этом отношении), если это значение существует в хэше (%hw_f), или же первое слово (или фраза) из $5 будет использоваться, когдаон существует в %hw_f. Если все условия не совпадают, фрагмент останется неизменным.

Я пробовал следующее:

s#(class="p_hw"><a href=")(http://[^<>"]*?xxxx\.com\/[^<>"]*[=/])([^<>"]*)(">(?:<b>)?)(.*?)(?=<)#
        my @n = split(/\,|;/, $5);
    my @m = map {s,^\s+|\s+$,,mgr} @n;
    my $new = $3 =~ s/^\s+|\s+$//mgr;
    my $new2 = $new =~ s/\+/ /mgr;
    exists $hw_f{$new2} ? "$1entry://$new2$4$5" : (exists $hw_f{$m[0]} ? "$1entry://$m[0]$4$5" : "$1$2$3$4$5") #eg;

%hw_f - это место, где будут сопоставляться все условия.

Выдает следующую ошибку:

Использование неинициализированного значения $ 1 в конкатенации (.) Или строки

Мне нужно получитьновое значение, основанное на $3 в пределах замещения, продолжите с этим новым значением. Как я мог это сделать?

Ответы [ 3 ]

3 голосов
/ 03 ноября 2019

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

1: используйте Regexp :: Common и URI для работы с URL. Почти никогда не стоит писать свои собственные регулярные выражения. Для анализа HTML с помощью регулярных выражений необходимо, чтобы вы серьезно знали, что делаете. https://metacpan.org/search?q=regexp%3A%3Acommon

2: всегда используйте только {} и // для переноса регулярных выражений. (Правило 99%)

3: Всегда сразу копируйте пронумерованные переменные в переменные my () со значимыми именами, если выражение не тривиально.

4: Модифицируйте массивы на месте с постфиксным foreach.

5: Расширьте форматирование кода, чтобы сделать его визуально привлекательным.

6: Используйте sprintf для сложных рекомбинаций переменных. Намного легче увидеть, какая переменная используется, где и для чего.

HTH

#  1                        2                                     3        4           5
s{(class="p_hw"><a href=\")(http://[^<>"]*?xxxx\.com/[^<>"]*[=/])([^<>\"]*)(\">(?:<b>)?)(.*?)(?=<)}{
    my ($m1, $m2, $m3, $m4, $m5) = ($1, $2, $3, $4, $5);
    my @n = split /[,|;]/, $m5;
    s/^\s+|\s+$//mg foreach @n;
    (my $new = $m3) =~ s/^\s+|\s+$//mg;
    (my $new2 = $new) =~ s/\+/ /g;
    exists $hw_f{$new2} ?
        sprintf "%sentry://%s%s%s", $m1, $new2, $m4, $m5 :
        exists $hw_f{$n[0]} ? 
        sprintf "%sentry://%s%s%s", $m1, $n[0], $m4, $m5 :
        "$m1$m2$m3$m4$m5";
}ige;
1 голос
/ 03 ноября 2019

Обновление:

while (<DICT>) {
s#(class="p_hw"><a href=")(http://[^<>"]*?wordinfo\.info\/[^<>"]*[=/])([^<>"]*)(">(?:<b>)?)(.*?)(?=<)#
        my $one = $1;
    my $two = $2;
    my $three = $3;
    my $four = $4;
    my $five = $5;
        my @n = split(/\,|;/, $5);
    my @m = map {s,^\s+|\s+$,,mgr} @n;
    my $new = $3 =~ s/^\s+|\s+$//mgr;
    my $new2 = $new =~ s/\+/ /mgr;
    exists $hw_f{$new2} ? $one."entry://$new2$four$five" : (exists $hw_f{$m[0]} ? $one."entry://$m[0]$four$five" : "$one$two$three$four$five") #eg;

    print $FH $_;
}

Назначение всех переменных захвата перед вызовом всего механизма regex как @DavidO в упомянутом комментарии, наконец, работает. Спасибо.

0 голосов
/ 03 ноября 2019

из вашего поста не очевидно, чего вы пытаетесь добиться. Если бы вы описали проблему в следующем формате, было бы легче понять

--- Пример -----------------------

Я извлекаю из веб-страницы фрагмент с <a href="http:\\......., который я хотел бы преобразовать / преобразовать в следующий формат <a href="http:\\........

По крайней мере, таким образом мы знаем, что такое INPUT и ожидаемый OUTPUT .

--- Конец примера ------------

Когда вы применяете регулярное выражение с память проще хранить запомненные значения в массиве или лучше хеш

use strict;
use warnings;

use Data::Dumper;

my %href;

$data = shift;

if( $data =~ /<a href="(\w+):\\\\([\w\d\.]+)\\([\w\d\.]+)\\(.+)">([^<]+)</ ) {
    @href{qw(protocol dns dir rest desc)} = ($1,$2,$3,$4,$5);
    print Dumper(\%href);
} else {
    print "No match found\n";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...