2010-03-27 14 views
2

Je ne peux pas pourquoi ce travail de code:Pourquoi un lookahead positif mène-t-il à des captures dans mon regex Perl?

$seq = 'GAGAGAGA'; 
my $regexp = '(?=((G[UCGA][GA]A)|(U[GA]CG)|(CUUG)))'; # zero width match 
while ($seq =~ /$regexp/g){ # globally 
    my $pos = pos($seq) + 1; # position of a zero width matching 
    print "$1 position $pos\n"; 
} 

Je sais que c'est un match nul largeur et dosn't mettre la chaîne en correspondance & $, mais pourquoi faut-il mettre dans 1 $?

merci!

Répondre

2

Votre expression régulière contient une capture (...), ce qui signifie que les variables $1, $2, etc. seront renseignées avec les résultats de ces captures. Cela fonctionne aussi dans les assertions de lookahead (bien que je ne crois pas que les assertions lookbehind, je crois).

Comme avec toutes les captures, si vous réécrivez (?:...) alors le contenu ne sera pas dans une variable de capture.

+0

Non, cela fonctionne dans lookbehind aussi. – ysth

6

Les correspondances sont capturées dans $1 en raison de toutes les parenthèses internes. Si vous ne voulez pas capturer, puis utilisez

my $regexp = '(?=(?:(?:G[UCGA][GA]A)|(?:U[GA]CG)|(?:CUUG)))'; 

ou mieux encore

my $regexp = qr/(?=(?:(?:G[UCGA][GA]A)|(?:U[GA]CG)|(?:CUUG)))/; 

De l'perlre documentation:

  • (?:pattern)
  • (?imsx-imsx:pattern)

Ceci est pour la mise en cluster, pas pour la capture; il regroupe les sous-expressions comme (), mais ne fait pas de références arrière comme c'est le cas pour (). Alors

@fields = split(/\b(?:a|b|c)\b/) 

est comme

@fields = split(/\b(a|b|c)\b/) 

mais ne produit pas des champs supplémentaires. Il est également moins cher de ne pas capturer des personnages si vous n'en avez pas besoin.

Toutes les lettres entre ? et : agissent comme modificateurs de drapeaux comme avec (?imsx-imsx). Par exemple,

/(?s-i:more.*than).*million/i 

est équivalent à plus bavard

/(?:(?s-i)more.*than).*million/i