Yo!
Quelqu'un de moins rouillé que moi au niveau des Regexp PHP saurait-il m'expliquer la différence fondamentale de fonctionnement dans ce code? ...
<?php
preg_match_all("@\\\$\{(.+)\}(?:\.([0-9]+))@iU", "\${12.5/100}.2", $evalParams);
var_dump($evalParams); // Capture bien le 2 dans le ".2"
preg_match_all("@\\\$\{(.+)\}(?:\.([0-9]+))?@iU", "\${12.5/100}.2", $evalParams);
var_dump($evalParams); // WTF ?
La présence de l'ungreedy est forcée car ma chaîne d'entrée peut ressembler à ceci:
"Vos sorts de soins directs placent également sur votre cible un bouclier qui absorbe un montant de dégâts égal à ${$m2/12.5}% du montant de points de vie rendus et dure $86273d. Chaque point de Maîtrise augmente le montant absorbé de ${$m2/100}.2% supplémentaires".
On remarque que seul le deuxième ${...} possède un attribut de précision (C'est typiquement du printf("%.02f")), sans l'ungreedy, la regexp fonctionne mais capture toute la moitié de la phrase...
Ça commence à me rendre fou cette affaire, je pense que si c'est impossible je vais tout simplement utiliser deux expressions régulières et basta.

À vue d'œil (mais à confirmer), vu que le ? peut prendre soit 0 soit 1 fois l'élément précédent, en ungreedy il va tenter d'en prendre 0 si c'est possible. Et vu qu'il n'y a plus aucune contrainte après, c'est complètement possible.
Tu devrais pouvoir forcer le 2ème à prendre le .2 en ajoutant un élément derrière. Dans le cas de ton exemple, ajouter un $ derrière devrait marcher. Dans le cas de la phrase que tu veux matcher, j'imagine que tu dois pouvoir ajouter le % ?
Uther Le 03/07/2013 à 12:27 Je ne m'y connais pas particulièrement en PHP mais en expression régulière, je me débrouille. Si j'ai bien compris tu veux capturer le contenu entre crochets et le nombre qui arrive juste après s'il existe.
Dans ce cas là ton expression devrait être \$\{(.+?)\}(?:\.([0-9]+))?
Il faut enlever le point d’interrogation final si tu ne veux capturer que lorsque les crochets sont suivis d'un point. N'étant pas un connaisseur de PHP, je te laisse faire l'échappement toi même.
Uther Le 06/07/2013 à 17:07 C'est le point d'interrogation en fin de l'expression que tu appelles ungreedy? Si c'est le cas, c'est normal qu'il ne fonctionne pas comme tu le souhaite car ce n'est absolument pas un "ungreedy".
Dans les expression régulière perl le point d'interrogation peut avoir pas mal de significations différentes selon l'endroit où il est placé:
-après un caractère, un groupe ou une classe, il indique que cet elément est optionnel (présent 0 ou une fois)
-après un quantifieur ( *, +, ?, {n,m}) il indique que ce quantifieur est ungreedy : il capturera seulement la quantité minimale permettant d'obtenir une correspondance valide
-en début de groupe, il indique un comportement particulier de ce groupe (non capturant, lookaroud, ...)
Dans ton exemple, le ? final n'est pas un ungreedy car il est placé en fin de groupe. Il indique que le groupe qui le précède est optionnel.
RHJPP Le 06/07/2013 à 19:01 Je pense que Warpten faisait référence au U qu'il plaçait après l'expression régulière. Et en effet, il n'est pas nécessaire puisqu'un ? a été placé après le +, seul endroit où il faut récupérer la chaîne la plus courte possible.
Uther Le 07/07/2013 à 16:44 Ok, vu que je fais plutôt du java, je ne connaissait pas cette option spécifique à PHP