2010-04-19 5 views
7

J'ai un mal de tête à la recherche de ceci: Comment utilisez-vous s /// dans une expression par opposition à une affectation. Pour clarifier ce que je veux dire, je suis à la recherche d'un équivalent de perl re.sub (...) python lorsqu'il est utilisé dans le contexte suivant:Comment puis-je utiliser // s/de Perl dans une expression?

newstring = re.sub('ab', 'cd', oldstring) 

La seule façon que je sais comment faire en perl jusqu'à présent est:

$oldstring =~ s/ab/cd/; 
$newstring = $oldstring; 

Notez l'affectation supplémentaire.

+4

Votre exemple définir à la fois '$ oldstring 'et' $ newstring' au texte révisé. Vouliez-vous dire de faire la cession avant la substitution et ensuite effectuer une substitution sur «$ newstring»? – mob

Répondre

7

Vous semblez avoir une idée fausse sur la façon dont =~ fonctionne. =~ est un opérateur de liaison qui associe une variable à un opérateur regexp. Il ne fait aucune affectation.

Les opérateurs d'expression rationnelle fonctionnent tous par défaut avec la variable de rubrique $_, donc s/foo/bar/; est identique à $_ =~ s/foo/bar/;. Aucune affectation n'a lieu. La variable de sujet est transformée.

Le cas est analogue lors de l'utilisation de n'importe quelle autre variable. $var =~ s/foo/bar/; transforme $var en remplaçant la première instance de foo par bar. Aucune affectation n'a lieu.

Le meilleur conseil que je peux vous donner est d'écrire Python en Python et Perl en Perl. Ne vous attendez pas à ce que les deux langues soient identiques.

Vous pourriez faire comme suggère DVK et écrire un sous-programme qui reproduira le comportement de substitution auquel vous êtes habitué.

Ou vous pourriez essayer du Perl idiomatique.Basé sur votre désir exprimé d'appliquer plusieurs transformations dans une ligne, j'ai fourni quelques exemples que vous pourriez trouver utiles.

J'utilise ici une boucle for sur un élément à thématiser $var et appliquer de nombreuses transformations codées en dur:

for($var) { 
    s/foo/bar/; 
    s/fizz/buzz/; 
    s/whop/bop-a-loo-bop/; 
    s/parkay/butter/; 
    s/cow/burger/; 
} 

Ou peut-être vous avez besoin d'appliquer un groupe de variables de transformations. Je définis un sous-programme pour faire une boucle sur une liste de références de tableau qui définissent les anciennes/nouvelles paires de transformation. Cet exemple tire parti du traitement des arguments orienté liste de Perl pour gérer n'importe quel nombre de transformations.

my $foo = transform(
    'abcd' => 
    [ 'a', 'b' ], 
    [ 'bb', 'c' ], 
    [ 'cc', 'd' ], 
    [ 'dd', 'DONE' ], 
); 

sub transform { 
    my $var = shift; 
    for (@_) { 
     my ($old, $new) = @$_; 
     $var =~ s/$old/$new/; 
    } 

    return $var; 
} 

Enfin un peu de vous embêter pour fournir une version de transformation qui modifie son premier argument:

my $foo = 'abcd'; 

transform_in_place(
    $foo => 
    [ 'a', 'b' ], 
    [ 'bb', 'c' ], 
    [ 'cc', 'd' ], 
    [ 'dd', 'DONE' ], 
); 

print "$foo\n"; 

sub transform_in_place { 
    for my $i (1..$#_) { 
     my ($old, $new) = @{$_[$i]}; 
     $_[0] =~ s/$old/$new/; 
    } 
} 

Pour mon projet, je serais probablement utiliser l'une des deux premières options en fonction de la besoins du problème particulier.

11

Vous pouvez utiliser ($new = $old) =~ s/whatever/whateverelse/; pour une exactement la même fonctionnalité que vous recherchez:

use strict; 
my $old = "OLD"; 
my $new; 
($new = $old) =~ s/OLD/NEW/; 
print "old=$old, new=$new"; 

Produit:

old=OLD, new=NEW 

Exactement ce que vous voulez

Si vous êtes à la recherche d'une fonction , vous pouvez simplement définir votre propre pour éviter l'affectation:

use strict; 
sub re_sub { 
    my ($find, $replace, $old) = @_; 
    my $new = $old; 
    $new =~ s/$find/$replace/; 
    return $new; 
} 

my $old = "ab"; 
my $new = re_sub('ab', 'cd', $old); 
print "new=$new\n"; 

Afficher les résultats dans new=cd.

7

La substitution d'expression régulière de Perl se produit toujours sur place. Donc, vous devez copier la chaîne à une nouvelle variable et fonctionne sur la nouvelle variable:

(my $newstring = $oldstring) =~ s/ab/cd/; 
+1

Basé sur ceci, ai-je raison de supposer que vous * ne pouvez pas * avoir deux s /// dans une ligne, une qui utilise le résultat de l'autre, sans assignations intermédiaires? – Mansour

+1

Alors que vous pourriez y parvenir en ajoutant des parenthèses et = ~ à la fin, il n'y a pas de syntaxe propre pour cela. –

2

Vous voulez avoir nouvellechaine $ soit le résultat de la substitution, non?

Quelque chose comme ceci:

($newstring = $oldstring) =~ s/ab/cd; 

devrait fonctionner. L'affectation définit $newstring à $oldstring, puis évalue à $newstring, sur quoi agit la substitution.

1

Sur cette base, ai-je raison de supposer que vous ne pouvez pas avoir deux s /// dans une ligne, une qui utilise le résultat de l'autre, sans assignations intermédiaires? - mikeY

Oui, vous avez raison. Si vous souhaitez appliquer plusieurs substitutions à la même chaîne que je ferais

$newstring = $oldstring ; 
    $newstring =~ s/ab/cd/ ; 
    $newstring =~ s/xx/yy/ ; 

Ce qui suit ne fonctionnera pas parce que s// renvoie le nombre de substitutions effectuées, pas la chaîne modifiée.

$newstring = $oldstring) =~ s/ab/cd/ =~ s/xx/yy/ ; 

En résumé, les opérations de regex de Perl sont très différentes de Python et vous êtes mieux essayer d'apprendre ce que Perl fait à partir de zéro plutôt que d'essayer de cartographier les concepts Python sur Perl

Questions connexes