Кто-нибудь может объяснить, почему этот код не работает?

#regex #perl #modifier

#регулярное выражение #perl #модификатор

Вопрос:

Я пытаюсь выполнить замену некоторых переменных в строку. Хэш содержит данные, строка $name — это формат. Он вставит две переменные, но не %M. Я сбит с толку. Я пробовал два разных сигнальных символа, а также заменял их пробелами и без пробелов. %M не входит. ????

 use Data::Dumper;

my %Sub = (A=>'Alan',G=>'42', M=>"Memories of Japan");
print "%Sub=n".Dumper(%Sub)."n====n";

my $name = "#M #A (#G).epub";
print "$namen====n";
$name =~ s/(#([AGM]))/($Sub{$2})/eeg;
print "$namen====n";

%Sub = (A=>'Bob',G=>'13', M=>'NightHawk');
print "%Sub=n".Dumper(%Sub)."n====n";
$name = "%M %A (%G).epub";
print "$namen====n";
$name =~ s/(%([AGM]))/($Sub{$2})/eeg;
print "$namen====n";
 

Комментарии:

1. Неважно… Неправильный код.

2. $name =~ s/(%([AGM]))/($Sub{$2})/eeg; По-прежнему не будет заменять строку пробелами.

3. Это регулярное выражение соответствует любому из A , G , I ( [AGI] класс символов) — нет M …?

4. Спасибо zdim. Я понял это поздно. Однако первое по-прежнему не работает со строкой с пробелами в ней.

5. Не могу сейчас написать правильный ответ… (1) нет необходимости ee , и это может быть очень опасно, и здесь нет необходимости даже в одном e (2) слишком большом количестве скобок… попробуйте этот однострочный: perl -wE'$n = "#M #A (#G)"; say $n; %h = (M => "x", A => "y", G => "z"); $n =~ s/#([AGM])/#$h{$1}/g; say $n'

Ответ №1:

Вы удвоили модификатор «e» в regexpr. Кроме того, в этом примере вы можете удалить его:

 use strict;
use warnings;
use Data::Dumper;

my %Sub = (A=>'Alan',G=>'42', M=>"Memories of Japan");
print "%Sub=n", Dumper(%Sub), "n====n";

my $name = "#M #A (#G).epub";
print "$namen====n";
$name =~ s/#([AGM])/$Sub{$1}/g;   #<-- changed
print "$namen====n";

%Sub = (A=>'Bob',G=>'13', M=>'NightHawk');
print "%Sub=n", Dumper(%Sub), "n====n";
$name = "%M %A (%G).epub";
print "$namen====n";
$name =~ s/%([AGM])/$Sub{$1}/g;   #<-- changed
print "$namen====n";
 

Ответ №2:

 s/.../($Sub{$2})/eeg
 

является сокращением для

 s/.../eval( ($Sub{$2}) )/eg    # For each match,
                               # execute eval( ($Sub{$2}) )
                               # and use the value returned.
 

Вы буквально просите Perl скомпилировать и выполнить значение $Sub{$2} как код Perl, но Memories of Japan это (обычно) недопустимый код Perl.

Ты хочешь

 s/.../$Sub{$2}/eg              # For each match,
                               # execute $Sub{$2}
                               # and use the value returned.
 

или даже

 s/.../$Sub{$2}/g               # For each match,
                               # execute qq/$Sub{$2}/
                               # (equivalent to "$Sub{$2}")
                               # and use the value returned.
 

Обратите внимание, что вы всегда должны использовать use strict; use warnings; . Это выявило бы проблему обработки NightHawk как кода Perl.