8796 sujets

Développement web côté serveur, CMS

Bonjour,

je rencontre un problème avec une regex.

Mon but est de remplacer les liens :

<a href="key-tourdefrance-2008.html">
// vers -->
<a href="/tags/tourdefrance-2008">


Ma fonction qui va bien :

$final = preg_replace('#href="key-(.*).html"#','href="/tags/$1" rel="tag"',$text,-1,$count);
echo 'Occurences trouvées : ' . $count;


Le problème, c'est que lorsque plusieurs liens se trouvent sur la même ligne, il ne traite que le premier lien. (Occurences trouvées : 1)
J'ai essayé les options s (singleline) et m (multiline) mais rien n'y fait.

Merci pour votre aide.
Salut,

En PHP, les quantifieurs de regex PCRE sont "gourmands" par défaut, ce qui signifie qu'il vont aussi loin qu'ils le peuvent tant que la regex est valide. Donc quand tu fais ça :
href="key-([#red].*[/#]).html"
...le quantifieur "astérisque" étant gourmand, ton point va matcher n'importe quel caractère en allant le plus loin possible, du moment qu'après on a ".html". Et donc, avec deux liens, il matche ça :
<a href=\"key-[#red]tourdefrance-2008.html\"><a href=\"key-tourdefrance-2008[/#].html\">

Tu as, comme très souvent, une liste assez longue de solutions disponibles, parmi lesquelles :
- inverser le comportement de tous les quantifieurs de ta regex (ils passeront ici de gourmands à non-gourmands) :
'#href="key-(.*).html"#[#red]U[/#]'
- inverser le comportement de l'astérisque en question (qui passera donc en non-gourmand)) :
'#href="key-(.*[#red]?[/#]).html"#'

- restreindre les caractères matchés par tes parenthèses, par exemple :
'#href="key-([#red][^.][/#]*).html"#'

Dernier point : ton ".html" devrait probablement être "\.html".
\o/ aaah.
Merci et merci pour ton explication Smiley smile

Aurais tu une idée de pourquoi cela marche si je saute une ligne entre chaque liens ?
C'est que la "gourmandise" s'arrête à chaque fin de ligne c'est ça ?
Modifié par supertino7 (19 Jul 2009 - 20:10)
a écrit :
C'est que la "gourmandise" s'arrête à chaque fin de ligne c'est ça ?
Non c'est que le point, c'est n'importe quoi sauf un retour à la ligne. Donc .*\.html matchera tout jusqu'au dernier ".html" de chaque ligne (essaye de mettre deux liens par ligne, tu verras).
Comme quasiment tout dans les regex, ce comportement peut lui aussi être changé si tu utilises le flag "s" en fin de regex. Là, le point vaudra vraiment "nimporte quoi".