Come posso eseguire una sostituzione Perl su una stringa mantenendo l'originale?
Domanda
In Perl, qual è un buon modo per eseguire una sostituzione su una stringa utilizzando un'espressione regolare e memorizzare il valore in una variabile diversa, senza modificare l'originale?
Di solito copio semplicemente la stringa in una nuova variabile e poi la associo a s///
regex che esegue la sostituzione sulla nuova stringa, ma mi chiedevo se esiste un modo migliore per farlo?
$newstring = $oldstring;
$newstring =~ s/foo/bar/g;
Soluzione
Questo è l'idioma che ho sempre usato per ottenere una copia modificata di una stringa senza cambiare l'originale:
(my $newstring = $oldstring) =~ s/foo/bar/g;
In perl 5.14.0 o successivo, potete utilizzare il nuovo /r
modificatore di sostituzione non distruttivo:
my $newstring = $oldstring =~ s/foo/bar/gr;
Nota:Le soluzioni di cui sopra funzionano senza g
pure.Funzionano anche con qualsiasi altro modificatore.
Altri suggerimenti
La dichiarazione:
(my $newstring = $oldstring) =~ s/foo/bar/g;
Che equivale a:
my $newstring = $oldstring;
$newstring =~ s/foo/bar/g;
In alternativa, a partire da Perl 5.13.2 è possibile utilizzare /r
per fare una sostituzione non distruttiva:
use 5.013;
#...
my $newstring = $oldstring =~ s/foo/bar/gr;
Sotto use strict
, Dire:
(my $new = $original) =~ s/foo/bar/;
Invece.
La soluzione a una riga è più utile come shibboleth che come buon codice;i bravi programmatori Perl lo conosceranno e lo capiranno, ma è molto meno trasparente e leggibile della coppia di due righe copia e modifica con cui stai iniziando.
In altre parole, un buon modo per farlo è il modo in cui sei Già facendolo.Una concisione inutile a scapito della leggibilità non è una vittoria.
Un'altra soluzione precedente alla 5.14: http://www.perlmonks.org/?node_id=346719 (vedi post di Japhy)
Come usa il suo approccio map
, funziona bene anche per gli array, ma richiede il collegamento a cascata map
per produrre un array temporaneo (altrimenti l'originale verrebbe modificato):
my @orig = ('this', 'this sucks', 'what is this?');
my @list = map { s/this/that/; $_ } map { $_ } @orig;
# @orig unmodified
Odio foo e bar..chi ha inventato comunque questi termini non descrittivi nella programmazione?
my $oldstring = "replace donotreplace replace donotreplace replace donotreplace";
my $newstring = $oldstring;
$newstring =~ s/replace/newword/g; # inplace replacement
print $newstring;
%: newword donotreplace newword donotreplace newword donotreplace
Se scrivi Perl con use strict;
, scoprirai che la sintassi su una riga non è valida, anche se dichiarata.
Con:
my ($newstring = $oldstring) =~ s/foo/bar/;
Ottieni:
Can't declare scalar assignment in "my" at script.pl line 7, near ") =~"
Execution of script.pl aborted due to compilation errors.
Invece, la sintassi che hai utilizzato, anche se una riga più lunga, è il modo sintatticamente corretto di farlo con use strict;
.Per me, usando use strict;
ormai è solo un'abitudine.Lo faccio automaticamente.Tutti dovrebbero.
#!/usr/bin/env perl -wT
use strict;
my $oldstring = "foo one foo two foo three";
my $newstring = $oldstring;
$newstring =~ s/foo/bar/g;
print "$oldstring","\n";
print "$newstring","\n";