¿Cómo realizo una sustitución Perl en una cadena mientras mantengo el original?

En Perl, ¿cuál es una buena manera de realizar un reemplazo en una cadena utilizando una expresión regular y almacenar el valor en una variable diferente, sin cambiar el original?

Normalmente solo copio la cadena a una nueva variable y luego la ato al s/// regex que hace el reemplazo en la nueva cadena, pero me preguntaba si hay una mejor manera de hacerlo.

 $newstring = $oldstring; $newstring =~ s/foo/bar/g; 

Esta es la expresión idiomática que siempre he usado para obtener una copia modificada de una cadena sin cambiar el original:

 (my $newstring = $oldstring) =~ s/foo/bar/g; 

En Perl 5.14.0 o posterior, puede usar el modificador de sustitución no destructivo nuevo /r :

 my $newstring = $oldstring =~ s/foo/bar/gr; 

Nota: Las soluciones anteriores funcionan sin g también. También funcionan con otros modificadores.

La statement:

 (my $newstring = $oldstring) =~ s/foo/bar/g; 

Lo cual es equivalente a:

 my $newstring = $oldstring; $newstring =~ s/foo/bar/g; 

Alternativamente, a partir de Perl 5.13.2 puede usar /r para hacer una sustitución no destructiva:

 use 5.013; #... my $newstring = $oldstring =~ s/foo/bar/gr; 

En use strict , decir:

 (my $new = $original) =~ s/foo/bar/; 

en lugar.

La solución de una línea es más útil como un código shibboleth que bueno; Los buenos progtwigdores de Perl lo sabrán y lo entenderán, pero es mucho menos transparente y legible que el colet de dos líneas para copiar y modificar que está comenzando.

En otras palabras, una buena manera de hacerlo es la forma en que ya lo está haciendo. La concisión innecesaria a costa de la legibilidad no es una ganancia.

Odio foo y bar … ¿quién inventó estos términos no descriptivos en la progtwigción de todos modos?

 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 

Otra solución anterior a 5.14: http://www.perlmonks.org/?node_id=346719 (vea la publicación de japhy)

Como su enfoque utiliza el map , también funciona bien para las matrices, pero requiere que el map cascada produzca una matriz temporal (de lo contrario, el original se modificaría):

 my @orig = ('this', 'this sucks', 'what is this?'); my @list = map { s/this/that/; $_ } map { $_ } @orig; # @orig unmodified 

Si escribe Perl con use strict; , entonces encontrará que la syntax de una línea no es válida, incluso cuando se declara.

Con:

 my ($newstring = $oldstring) =~ s/foo/bar/; 

Usted obtiene:

 Can't declare scalar assignment in "my" at script.pl line 7, near ") =~" Execution of script.pl aborted due to comstacktion errors. 

En cambio, la syntax que ha estado usando, mientras que una línea más larga, es la forma sintácticamente correcta de hacerlo con use strict; . Para mí, usando el use strict; es solo un hábito ahora. Lo hago automáticamente Todos deberían.

 #!/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";