Come posso eseguire una sostituzione Perl su una stringa mantenendo l'originale?

StackOverflow https://stackoverflow.com/questions/22836

  •  09-06-2019
  •  | 
  •  

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;
È stato utile?

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";
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top