2012-11-22 2 views
1

Dans un code Perl/Tk Je trouve une déclaration conditionnelle comme ci-dessousEn Perl, quelle est la signification de if (s/^ + //)?

if (s/^\+//) 
{ 
    #do something 
} 
elsif (/^-/) 
{ 
    #do another thing 
} 

On dirait que certains pattern matching a été fait. Mais je ne peux pas le comprendre. Quelqu'un peut-il m'aider à comprendre ce modèle de correspondance?

+2

@Oded, ce lien ISN Ce n'est pas le pire tutoriel Perl que j'ai jamais vu, mais il est plutôt ancien et utilise quelques pratiques obsolètes ('-w' vs' warnings', prototypes). Je pourrais recommander ['perldoc perlretut'] (http://p3rl.org/retut). –

+0

@JoelBerger - Ça va. C'était le premier coup de google. – Oded

+3

@Oded, NP. La longévité des tutoriels Perl est quelque chose que la communauté essaie de combattre en faisant/en mettant en évidence de nouveaux meilleurs, et en avertissant sur les anciens/mauvais http://perl-tutorial.org/. Perl a eu une mauvaise réputation après que le boom de dot-com ait apporté beaucoup de mauvais code, nous essayons de faire un meilleur tutoriel à la fois. –

Répondre

11

Ce sont les deux expressions régulières. Vous pouvez lire sur eux au perlre et perlretut. Vous pouvez jouer avec eux sur http://www.rubular.com.

Ils font tous deux implicitement quelque chose avec $_. Il y a probablement un while ou foreach autour de vos lignes de code sans une variable de boucle. Dans ce cas, $_ devient cette variable de boucle. Il peut par exemple contenir la ligne en cours d'un fichier en cours de lecture.

  1. Si la valeur actuelle de $_ contient un signe + (plus) comme premier caractère au début de la chaîne, #do somehting.
  2. Sinon, s'il contient un signe - (minus), #do another thing.

Dans le cas 1., il remplace également le signe + par rien (c'est-à-dire qu'il le supprime). Il ne supprime pas le - dans 2. cependant.


Regardons une explication avec YAPE::Regex::Explain.

use YAPE::Regex::Explain; 
print YAPE::Regex::Explain->new(qr/^\+/)->explain(); 

La voici. Pas vraiment utile dans notre cas, mais un bel outil quand même. Notez que les parties (?-imsx et ) sont les éléments par défaut que Perl suggère. Ils sont toujours là sauf si vous les changez.

The regular expression: 

(?-imsx:^\+) 

matches as follows: 

NODE      EXPLANATION 
---------------------------------------------------------------------- 
(?-imsx:     group, but do not capture (case-sensitive) 
         (with^and $ matching normally) (with . not 
         matching \n) (matching whitespace and # 
         normally): 
---------------------------------------------------------------------- 
^      the beginning of the string 
---------------------------------------------------------------------- 
    \+      '+' 
---------------------------------------------------------------------- 
)      end of grouping 
---------------------------------------------------------------------- 

Mise à jour: Comme Mikko L dans les commentaires ont souligné, vous devriez peut-être factoriser/changer ce morceau de code. Bien qu'il fasse probablement ce qu'il est censé faire, je crois que ce serait une bonne idée de le rendre plus lisible. Celui qui l'a écrit ne se souciait évidemment pas de vous en tant que mainteneur tardif. Je vous suggère de faire. Vous pouvez le modifier en:

# look at the content of $_ (current line?) 
if (s/^\+//) 
{ 
    # the line starts with a + sign, 
    # which we remove! 

    #do something 
} 
elsif (m/^-/) 
{ 
    # the line starts witha - sign 
    # we do NOT remove the - sign! 

    #do another thing 
} 
+1

Votre analyse est spot-on. J'ajouterais que le PO devrait envisager de refactoriser ce morceau de code afin que la substitution soit plus évidente. Il est très facile de le manquer comme il est écrit maintenant. Même aller simplement à 'if (/^\ + /) {$ _ = ~ s/^ \ + //; # faire quelque chose} 'aiderait considérablement. –

+0

@MikkoL Je suis d'accord et ajouté les suggestions. Je ne suis pas d'accord avec l'utilisation explicite de $ _, mais c'est une préférence personnelle, je crois. Je vous remercie. – simbabque

+1

Downvoter, vous souciez-vous de commenter comment je peux améliorer mon poste? – simbabque

5

Ce sont des expressions régulières, utilisées pour la correspondance de formes et la substitution.

Vous devriez lire sur le concept, mais comme pour votre question:

s/^\+// 

Si la chaîne a commencé avec un plus, supprimer ce plus (le "s" signifie "substitut"), et return true .

/^-/ 

Vrai si la chaîne commence par un signe moins.

3

Ce code est équivalent à

if ($_ =~ s/^\+//) { # s/// modifies $_ by default 
    #do something 
} 
elsif ($_ =~ m/^-/) { # m// searches $_ by default 
    #do another thing 
} 

s/// et m// sont les opérateurs de apostrophe regexp. Vous pouvez lire à leur sujet dans perlop.

+2

C'est une réponse parfaitement bonne (quoique courte). Je ne vois pas pourquoi il a été déprécié. – simbabque

+1

Je n'ai pas downvote, mais je suis sûr que c'est parce que la variable implicite n'est pas en cause ici, mais plutôt le modèle de substitution lui-même. –

2

Les autres réponses ont donné un résumé du fonctionnement du code, mais pas beaucoup de pourquoi. Voici un exemple simple de la raison pour laquelle on pourrait utiliser une telle logique.

#!/usr/bin/env perl 

use strict; 
use warnings; 

my $args = {}; 

for (@ARGV) { 
    if (s/^no//) { 
    $args->{$_} = 0; 
    } else { 
    $args->{$_} = 1; 
    } 
} 

use Data::Dumper; 
print Dumper $args; 

Lorsque vous appelez le script comme

./test.pl hi nobye 

vous obtenez

$VAR1 = { 
      'hi' => 1, 
      'bye' => 0 
     }; 

La clé est la chaîne, si elle est précédée par no puis retirez-le (pour obtenir la clé en question) et placez plutôt la valeur à 0.

L'exemple de l'OP est un peu plus impliqué, mais suit la même logique.

  • si le début clé avec un +, retirez-le et faire quelque chose
  • si le début clé avec un -, ne suppriment pas et faire quelque chose d'autre
+0

@downvoter, vous voulez faire un commentaire? –

Questions connexes