Pergunta

Em Perl, qual é uma boa maneira de realizar uma substituição em uma string usando uma expressão regular e armazenar o valor em uma variável diferente, sem alterar o original?

Normalmente, apenas copio a string para uma nova variável e depois vinculo-a ao s/// regex que faz a substituição na nova string, mas queria saber se existe uma maneira melhor de fazer isso?

$newstring = $oldstring;
$newstring =~ s/foo/bar/g;
Foi útil?

Solução

Esta é a expressão que sempre usei para obter uma cópia modificada de uma string sem alterar o original:

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

No perl 5.14.0 ou posterior, você pode usar o novo /r modificador de substituição não destrutivo:

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

Observação:As soluções acima funcionam sem g também.Eles também funcionam com quaisquer outros modificadores.

Outras dicas

A declaração:

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

O que equivale a:

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

Alternativamente, a partir do Perl 5.13.2 você pode usar /r para fazer uma substituição não destrutiva:

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

Sob use strict, dizer:

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

em vez de.

A solução de uma linha é mais útil como uma palavra de ordem do que um bom código;bons codificadores Perl saberão e entenderão, mas é muito menos transparente e legível do que o dístico de copiar e modificar de duas linhas com o qual você está começando.

Em outras palavras, uma boa maneira de fazer isso é a maneira como você está Fazendo.A concisão desnecessária ao custo da legibilidade não é uma vitória.

Outra solução pré-5.14: http://www.perlmonks.org/?node_id=346719 (veja a postagem de japhy)

Como sua abordagem usa map, também funciona bem para matrizes, mas requer cascata map para produzir um array temporário (caso contrário o original seria modificado):

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

Eu odeio foo e bar ..quem inventou esses termos não descritivos em programação?

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 você escrever Perl com use strict;, você descobrirá que a sintaxe de uma linha não é válida, mesmo quando declarada.

Com:

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

Você obtém:

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

Em vez disso, a sintaxe que você está usando, embora seja uma linha mais longa, é a maneira sintaticamente correta de fazer isso com use strict;.Para mim, usando use strict; é apenas um hábito agora.Eu faço isso automaticamente.Todo mundo deveria.

#!/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";
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top