Como faço uma substituição Perl em uma string mantendo o original?
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;
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á já 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";