web-dev-qa-db-fra.com

Perl regex et groupes de capture

Les impressions suivantes ac | a | bbb | c

    #!/usr/bin/env Perl
    use strict;
    use warnings;
   # use re 'debug';

    my $str = 'aacbbbcac';

    if ($str =~ m/((a+)?(b+)?(c))*/) {
       print "$1 | $2 | $3 | $4\n";
    }

il semble que les correspondances échouées ne réinitialisent pas les variables de groupe capturées. que me manque-t-il?

merci,

9
snoofkin

il semble que les correspondances ratées ne réinitialisent pas les variables du groupe capturé

Il n'y a pas de correspondance ratée ici. Votre regex correspond à la chaîne bien. Bien que certaines correspondances aient échoué pour des groupes internes dans certaines répétitions. Chaque groupe mis en correspondance peut être écrasé par la prochaine correspondance trouvée pour ce groupe particulier ou conserver la valeur de la correspondance précédente si ce groupe ne correspond pas à la répétition actuelle.

Voyons comment se déroule la correspondance de regex:

  • Le premier (a+)?(b+)?(c) correspond à aac. Puisque (b+)? est facultatif, cela ne sera pas mis en correspondance. A ce stade, chaque groupe de capture contient la partie suivante:

    • $1 contient la correspondance entière - aac
    • $2 contient (a+)? partie - aa
    • $3 contient (b+)? partie - null.
    • $4 contient (c) partie - c
  • Puisqu'il reste encore une chaîne à faire correspondre - bbbcac. En continuant - (a+)?(b+)?(c) correspond - bbbc. Puisque (a+)? est facultatif, cela ne sera pas mis en correspondance.

    • $1 contient la correspondance entière - bbbc. Ecrase la valeur précédente dans $1
    • $2 ne correspond pas. Donc, il contiendra du texte précédemment apparié - aa
    • $3 cette fois correspond. Il contient - bbb
    • $4 correspond à c 
  • Encore une fois, (a+)?(b+)?(c) correspondra à la dernière partie - ac.

    • $1 contient la correspondance entière - ac
    • $2 correspond à a cette fois. Ecrase la valeur précédente dans $2. Il contient maintenant - a
    • $3 ne correspond pas cette fois, car il n'y a pas de pièce (b+)?. Ce sera la même chose que pour le match précédent - bbb
    • $4 correspond à c. Ecrase la valeur de la correspondance précédente. Il contient maintenant - c.

Maintenant, il ne reste plus rien dans la chaîne à faire correspondre. La valeur finale de tous les groupes de capture sont:

  • $1 - ac
  • $2 - a
  • $3 - bbb
  • $4 - c.
15
Rohit Jain

Aussi étrange que cela puisse paraître, il s'agit du comportement "attendu". Voici une citation de perlre docs:

REMARQUE: Les correspondances échouées dans Perl ne réinitialisent pas les variables de correspondance, ce qui facilite l'écriture de code qui teste une série de cas plus spécifiques et se souvient de la meilleure correspondance.

1
Paul Rubel

Pour le groupe de parenthèses, /(\d+)/ This documentation dit d’utiliser\1 \2 ...ou \g{1} \g{2}. L'utilisation de $1 or $2... dans une partie regex de substitution provoquera une erreur du type: scalaire trouvée dans motif

# Example to turn a css href to local css.
# Transforms <link href="http://..." into <link href="css/..."

# ... inside a loop ...

my $localcss = $_; # one line from the file
$localcss =~ s/href.+\/([^\/]+\.css")/href="css\/\1/g ;
0
Sergio Abreu