2010-07-23 6 views
9

Normalement, si vous souhaitez modifier une variable regex vous faites ceci:Comment faire perl inline regex sans paramétrer une variable?

$string =~ s/matchCase/changeCase/; 

Mais est-il possible de simplement faire la ligne sans remplacer la mise en arrière à la variable?

Je souhaite utiliser quelque chose comme ceci:

my $name="jason"; 
print "Your name without spaces is: " $name => (/\s+/''/g); 

Quelque chose comme ça, un peu comme la fonction preg_replace en PHP.

+1

L'interface de l'opérateur de substitution n'est pas un bon conception. [(J'ai déjà dit quelque chose comme ça une fois aujourd'hui.)] (Http://stackoverflow.com/questions/3319170#comment-3443516) On parle de [p5p] (http://www.socialtext.net/perl5 /index.cgi?p5p) pour y ajouter un drapeau afin qu'il renvoie la chaîne modifiée. – daxim

Répondre

11

Révisé pour Perl 5.14.

Depuis 5,14, avec le drapeau /r-retour la substitution, vous pouvez le faire:

print "Your name without spaces is: [", do { $name =~ s/\s+//gr; } 
    , "]\n"; 

Vous pouvez utiliser map et une variable lexicale.

my $name=" jason "; 

print "Your name without spaces is: [" 
    , (map { my $a = $_; $a =~ s/\s+//g; $a } ($name)) 
    , "]\n"; 

Maintenant, vous devez utiliser un lexique car $ _ sera alias et donc modifier votre variable.

La sortie est

Your name without spaces is: [jason] 
# but: $name still ' jason ' 

Il est vrai que do fonctionnera tout aussi bien (et peut-être mieux)

print "Your name without spaces is: [" 
    , do { my ($a = $name) =~ s/\s+//g; $a } 
    , "]\n"; 

Mais la copie lexicale est toujours là. La cession dans le my est une abréviation que certaines personnes préfèrent (pas moi).

Pour cet idiome, j'ai développé un opérateur que j'appelle filter:

sub filter (&@) { 
    my $block = shift; 
    if (wantarray) { 
     return map { &$block; $_ } @_ ? @_ : $_; 
    } 
    else { 
     local $_ = shift || $_; 
     $block->($_); 
     return $_; 
    } 
} 

Et vous appelez comme ceci:

print "Your name without spaces is: [", (filter { s/\s+//g } $name) 
    , "]\n"; 
+3

Ou vous pouvez utiliser une variable lexicale sans utiliser 'map':' print "Votre nom sans espaces est: [", do {my $ a = $ name; $ a = ~ s/\ s + // g; $ a}, "] \ n" ' – mob

+1

@mobrule: J'ajoutais ça en tapant. : D – Axeman

+0

A accepté celui-ci car il a plus d'explications. –

1
print "Your name without spaces is: @{[map { s/\s+//g; $_ } $name]}\n";