Comment dois-je effectuer une substitution Perl sur une chaîne tout en en gardant l'original?

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

  •  09-06-2019
  •  | 
  •  

Question

En Perl, ce qui est un bon moyen pour effectuer un remplacement sur une chaîne à l'aide d'une expression régulière et de stocker la valeur dans une variable différente, sans modification de l'original?

J'ai l'habitude de simplement copier la chaîne de caractères à une variable, puis le lier à la s/// regex qui ne le remplacement sur la nouvelle chaîne, mais je me demandais si il ya une meilleure façon de le faire?

$newstring = $oldstring;
$newstring =~ s/foo/bar/g;
Était-ce utile?

La solution

C'est l'idiome, j'ai toujours utilisé pour obtenir une copie modifiée d'une chaîne sans modification de l'original:

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

En perl 5.14.0 ou version ultérieure, vous pouvez utiliser le nouveau /r non-destructive de substitution modificateur:

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

Note:Les solutions ci-dessus travail sans g trop.Ils travaillent également avec tous les autres modificateurs.

Autres conseils

La déclaration:

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

Ce qui est équivalent à:

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

Sinon, comme le Perl 5.13.2 vous pouvez utiliser /r pour faire un non destructive de substitution:

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

En vertu de use strict, dire:

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

au lieu de cela.

Le one-liner solution est plus utile qu'un shibboleth que du bon code;bon Perl codeurs vont la connaître et la comprendre, mais c'est beaucoup moins transparente et moins lisible que le copier-modifier couplet vous débutez avec.

En d'autres termes, un bon moyen pour ce faire est la façon dont vous êtes déjà de le faire.Inutile de concision au détriment de la lisibilité n'est pas une victoire.

Un autre pré-5.14 solution: http://www.perlmonks.org/?node_id=346719 (voir japhy du post)

Comme son approche utilise map, il travaille aussi bien pour les tableaux, mais exige en cascade map pour produire un tableau temporaire (à défaut de l'original serait modifié):

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

Je déteste les foo et bar ..qui a imaginé ces termes descriptifs dans la programmation de toute façon?

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

Si vous écrivez avec Perl use strict;, alors vous trouverez que la syntaxe de la ligne n'est pas valide, même lorsqu'ils sont déclarés.

Avec:

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

Vous obtenez:

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

Au lieu de cela, la syntaxe que vous utilisez, alors qu'une ligne de plus, est syntaxiquement correct façon de le faire avec use strict;.Pour moi, à l'aide de use strict; est juste une habitude maintenant.Je le fais automatiquement.Tout le monde devrait.

#!/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";
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top