2010-08-25 7 views
2

Lorsque vous utilisez l'opérateur not ^ en combinaison avec une référence arrière, pourquoi ai-je besoin d'utiliser une correspondance paresseuse? Il semble que le not devrait casser le match.Pourquoi cette regex, en utilisant "not" & un backref, nécessite-t-elle une correspondance paresseuse?

Par exemple:

<?php 
preg_match('/(t)[^\1]*\1/', 'is this test ok', $matches); 
echo $matches[0]; 
?> 

Will output this test, au lieu de this t, malgré le fait que le milieu t ne correspond pas à [^\1]. Je dois utiliser /(t)[^\1]*?\1/ to match this t.

De plus

preg_match('/t[^t]*t/', 'is this test ok', $matches); 

does match only this t.

Que se passe-t-il et qu'est-ce que je ne comprends pas?

Répondre

5

Cela ne fonctionne pas car le \1 n'est pas une référence arrière dans une classe de caractères, le \1 est interprété comme le caractère avec la valeur ASCII 1.

Vous pouvez utiliser un lookaround négatif au lieu d'obtenir l'effet souhaité:

'/(t)(?:(?!\1).)*\1/' 
+0

je venais ajouté cet exemple précis à ma propre réponse. Je suppose que les grands esprits se ressemblent. ;-) –

+0

Merci, les regex m'obtiennent à chaque fois! –

2

Vous ne pouvez pas utiliser les références arrière dans les classes de caractères. [^\1] signifie "tout caractère autre que 1". En revanche, utilisez /(t)(?:(?!\1).)*\1/.

(?:...) est un groupe non-capture

(?!...) est un "look-ahead négatif", affirmant que la sous-expression ne correspond pas à

(?!\1)., quand \1 est un seul caractère, signifie « tout caractère cela ne correspond pas \1