2009-08-13 6 views
3

J'essaie de faire correspondre les sous-chaînes qui sont entourées de%, mais preg_match_all semble en inclure plusieurs en même temps dans la même ligne.Regex pour faire correspondre la chaîne entre%

code

ressemble à ceci:

preg_match_all("/%.*%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches); 
print_r($matches); 

qui produit la sortie suivante.

Array 
(
    [0] => Array 
     (
      [0] => %hey%_thereyou're_a%rockstar% 
      [1] => %there% 
     ) 

) 

Cependant, je voudrais que ce produit à la place le tableau suivant:

[0] => %hey% 
[1] => %rockstar% 
[2] => %there% 

Qu'est-ce que je manque?

Répondre

12

Remplacer le « . » dans l'expression régulière avec « [^%] « :

preg_match_all("/%[^%]*%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches); 

Ce qui se passe est que le » . » est « avidement » en faisant correspondre autant qu'il le peut, y compris tout Up- au% final sur la ligne. En le remplaçant par la classe de caractères nuls "[^%]", cela signifie qu'il va correspondre à à l'exception de pour cent, ce qui le fera correspondre exactement aux bits que vous voulez.

Une autre option serait de placer un « ? » après le point, ce qui indique qu'il « ne soyez pas gourmand »:

preg_match_all("/%.*?%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches); 

Dans l'exemple ci-dessus, ou l'autre option fonctionne, mais il y a des moments lorsque vous cherchez peut-être quelque chose de plus grand qu'un seul caractère, une classe de caractères niée ne vous aidera pas, alors la solution est de ne pas grever la correspondance.

+0

Cela fonctionne. Merci! – Spoike

4

Vous faites un match gourmand - utiliser ? pour le rendre ungreedy:

/%.*?%/ 

Si un saut de ligne peut se produire à l'intérieur du match, ajouter le modificateur s (DOTALL):

/%.*?%/s 
1

La raison en est que l'étoile est gourmande. C'est-à-dire que l'étoile fait que le moteur regex répète le jeton précédent aussi souvent que possible. Tu devrais essayer .*? au lieu.

1

Vous pouvez essayer /%[^%]+%/ - cela signifie entre les signes de pourcentage que vous voulez seulement correspondre à des caractères qui ne sont pas des signes de pourcentage.

Vous pourriez également rendre le motif non transparent, par ex. /%.+%/U, donc il va capturer le moins possible (je pense).

+0

Plus précisément, '/ U' inverse la gourmandise de tous les quantificateurs de la regex, donc' /%.+%/ U' est le même que '/%.+?% /', et '/%.+?%/U' est le même que '/%.+%/'. http://www.php.net/manual/fr/reference.pcre.pattern.modifiers.php –

2

Ajouter un? après le *:

preg_match_all("/%.*?%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches); 
1

|% (\ w +)% | Cela fonctionnera exactement ce que vous voulez.