Perl: usa i backreference in una variabile stringa di sostituzione
Sto eseguendo una sostituzione di stringhe in Perl, ma ho sia il pattern che le stringhe di sostituzione memorizzate come variabili scalari al di fuori degli operatori di espressioni regolari. Il problema è che voglio che la stringa di sostituzione sia in grado di utilizzare i riferimenti a ritroso.
Spero che il codice seguente illustrerà la questione in modo più chiaro.
my $pattern = 'I have a pet (\w+).';
my $replacement = 'My pet $1 is a good boy.';
my $original_string = 'I have a pet dog.';
# Not Working
my $new_string = $original_string =~ s/$pattern/$replacement/r;
# Working
#my $new_string = $original_string =~ s/$pattern/My pet $1 is a good boy./r;
# Expected: "My pet dog is a good boy."
# Actual: "My pet $1 is a good boy."
print "$new_string\n";
Risposte
s/$pattern/My pet $1 is a good boy./
è l'abbreviazione di
s/$pattern/ "My pet $1 is a good boy." /e
L'espressione di sostituzione ( "My pet $1 is a good boy."
) è una stringa letterale che esegue l'interpolazione $1
.
Ciò significa che
s/$pattern/$replacement/
è l'abbreviazione di
s/$pattern/ "$replacement" /e
L'espressione di sostituzione ( "$replacement"
) è una stringa letterale che interpola $replacement
(non $1
).
Sebbene possa ostacolarti, è una buona cosa perl
non avere l'abitudine di eseguire il contenuto delle variabili come codice Perl. :)
Puoi usare gsub_copy
from String::Substitution per risolvere il tuo problema.
use String::Subtitution qw( gsub_copy );
my $pattern = 'I have a pet (\w+)\.';
my $replacement = 'My pet $1 is a good boy.';
my $original_string = 'I have a pet dog.';
my $new_string = gsub_copy($original_string, $pattern, $replacement);
Quello $1
nella stringa di sostituzione è solo caratteri successivi $
e 1
, e per trasformarlo in una variabile per la prima acquisizione dovresti passare attraverso dei cattivi cerchi. †
Che ne dici di un'alternativa
my string = q(a pet dog);
my $pattern = qr/a pet (\w+)/;
my $new = $string =~ s/$pattern/ repl($1) /er;
sub repl {
my ($capture) = @_;
return "$capture is a good boy";
}
dove il sottotitolo è davvero giusto
sub repl { "$_[0] is a good boy" }
È un po' di più ma poi è più capace e flessibile.
† Oppure, come risulta dalla risposta di ikegami, usa String::Substitution che racchiude tutte le "sottigliezze" coinvolte in una singola chiamata