web-dev-qa-db-fra.com

Perl Regex 'e' (eval) modificateur avec s ///

J'ai un peu de difficulté à comprendre cette utilisation simple du modificateur de regex/e.

my $var = 'testing';
$_ = 'In this string we are $var the "e" modifier.';

s/(\$\w+)/$1/ee;

print;

Retourne: "Dans cette chaîne, nous testons le modificateur" e "."

Je ne vois pas pourquoi deux modificateurs «e» sont nécessaires. Autant que je sache, $ 1 devrait capturer '$ var' à partir de la chaîne et un seul modificateur 'e' devrait alors pouvoir remplacer la variable par sa valeur. Je dois cependant mal comprendre quelque chose, car essayer le code ci-dessus avec un seul modificateur 'e' ne remplace visiblement rien dans la chaîne.

Excusez-moi de poser une question aussi simple!

Merci.

30
Pete171

Ce n’est pas vraiment une question «simple», alors ne vous en faites pas.

Le problème est qu’avec un seul /e, le RHS est censé être un code dont le résultat eval ’d est utilisé pour le remplacement.

Qu'est-ce que c'est RHS? C'est $1. Si vous avez évalué $1, vous trouvez que contient la chaîne $var. Il ne contient pas le contenu de cette variable, mais simplement $ suivi d'une v suivie d'une a suivie d'une r

Par conséquent, vous devez l’évaluer deux fois, une fois pour transformer $1 en $var, puis de nouveau pour transformer le résultat précédent de $var dans la chaîne "testing". Vous faites cela en ayant le modificateur double ee sur l'opérateur s .

Vous pouvez vérifier cela assez facilement en l'exécutant avec un /e plutôt que deux. Voici une démonstration à la fois, ainsi qu’une troisième méthode utilisant la déréférencement symbolique - qui, comme elle fait référence à la table des symboles de package, ne fonctionne que sur les variables de package.

use v5.10;

our $str = q(In this string we are $var the "e" modifier.);
our $var = q(testing);

V1: {
    local $_ = $str; 
    s/(\$\w+)/$1/e;
    say "version 1: ", $_;

}

V2: {
    local $_ = $str;
    s/(\$\w+)/$1/ee;
    say "version 2: ", $_;
}

V3: {
    no strict "refs";
    local $_ = $str;
    s/\$(\w+)/$$1/e;
    say "version 3: ", $_;
}

Lorsqu'il est exécuté, cela produit:

version 1: In this string we are $var the "e" modifier.
version 2: In this string we are testing the "e" modifier.
version 3: In this string we are testing the "e" modifier.
39
tchrist

Pour être clair, le formulaire s//ee ne modifie pas du tout votre motif regex ni son interprétation. Il s'agit d'un traitement facultatif de la chaîne latérale de remplacement après l'exécution de la regex. (Voir Opérateurs similaires à PERLOP Regex

Les e ou ee viennent juste d’être mélangés aux options de regex du côté PATTERN du formulaire s/PATTERN/REPLACEMENT/msixpodualgcer

De Perlop:

Les options sont identiques à m // avec l’ajout Des options spécifiques de remplacement Suivantes:

e Evaluate the right side as an expression.
ee  Evaluate the right side as a string then eval the result.
r   Return substitution and leave the original string untouched.

Vous pouvez voir le même comportement de type e contre ee dans des situations non regex, comme le montre cet exemple:

#!/usr/bin/Perl 
use warnings;
use strict;

my $var = "var's contents";
my $str='"-> $var <-"';
print eval('$str'), "\n";        # equivalent to s//e
print eval(eval('$str')), "\n";  # equivalent to s//ee

Sortie:

"-> $var <-"
-> var's contents <-
8
the wolf

Essayez l’utilitaire de changement de nom du dernier paquet Perl avec:

rename -v 's/\b(\w)/uc($1)/eg' *

Ici, le modèle \b trouve la limite de Word et le modificateur e permet l'évaluation dans la substitution, et g remplace l'occurrence all.

Vous pouvez également renommer camelCase avec:

rename -v 's/\b(\w)/uc($1)/eg' *
rename -v 's/^(\w)/lc($1)/e' *
rename -v 's/\s+//g' *
0
Xiè Jìléi