Expressions régulières : choisissez le meilleur délimiteur !

Attention, cet article a été posté en 2008. Il est possible que les informations mentionnées ne soient plus d'actualité, ou que mon opinion ait évolué. Merci d'en tenir compte lors de votre lecture.

Converti il y a maintenant quelques années, par Yves Maistriaux en personne (grand gourou français des expressions régulières), j'utilise l'accent grave ` comme délimiteur pour mes regex. Comme beaucoup me posent la question sur les forums que je fréquente, j'ai décidé d'expliquer ici les raisons de ce choix.

La documentation PHP le précise, n'importe quel caractère peut être utilisé comme délimiteur, en dehors de l'anti-slashe « \ » et des caractère alpha-numériques. Toutefois, il existe les bons délimiteurs, et les autres...

Certains sites web recommandent l'utilisation du pipe « | » comme délimiteur. C'est selon moi une grave erreur. Pourquoi ? Parce qu'il s'agit d'un métacaractère ! Pour vous en convaincre, analysons ensemble le code suivant :

<?php
$texte = 'bonsoir ou bonjour ?';
echo preg_replace('|bon|', '', $texte); // Affiche : soir ou jour ?

Cela fonctionne parfaitement. Mais maintenant, si nous souhaitons affiner notre masque, en ne remplaçant que les « bon » suivis par « jour » ou « soir » :

$texte = 'bonsoir ou bonjour ?';
echo preg_replace('|bon(jour|soir)|', '$1', $texte);
// Renvoie une erreur !

Une idée serait d'échapper le pipe utilisé comme métacaractère, en le précédant par un anti-slashe « \ » :

$texte = 'bonsoir ou bonjour ?';
echo preg_replace('|bon(jour\|soir)|', '$1', $texte);
// Affiche : bonsoir ou bonjour ?

Et oui, un métacaractère échappé n'est plus reconnu comme tel : il est donc vu comme un simple caractère... Et donc notre masque ne fonctionne plus !

Cette exemple reste vrai pour tous les métacaractères (accent circonflexe « ^ », dollar « $ », crochets, parenthèses, etc.).


D'autres sites web recommandent l'utilisation du point d'exclamation « ! ». Ce n'est pas vraiment un métacaractère, certes. Ou du moins, la documentation PHP ne le définie pas comme tel. Cependant, ça reste une erreur, car le point d'exclamation est utilisé pour les assertions arrières négatives. Regardons l'exemple suivant :

$texte = 'bonsoir ou bonjour ?';
echo preg_replace('!bon(?!soir)!i', '', $texte);
// Renvoie une erreur !

Ce code est censé remplacer toutes les chaînes « bon » non suivies par « soir ». Seulement, l'utilisation du point d'exclamation en délimiteur entre en conflit avec l'assertion arrière négative : ce code ne fonctionnera pas ! Ici aussi, échapper le point d'exclamation ne renvoie pas le résultat souhaité :

$texte = 'bonsoir ou bonjour ?';
echo preg_replace('!bon(?\!soir)!i', '', $texte);
// Affiche : bonsoir ou bonjour ?

Pas de chance, cela ne fonctionne pas !


Bien entendu, il existe d'autres caractères intelligents, comme le dièze « # ». Cependant, il est utilisé pour les codes couleurs, ce qui nous obligerait à l'échapper quand l'occasion se présentera. Ce n'est pas un mal en soit, cela fonctionne parfaitement dans ce cas, mais il faut y penser. C'est pourquoi je suis fidèle à l'accent grave ` depuis tant d'années.

À ce jour, c'est selon moi le meilleur délimiteur.

Vos réflexions

Oui ok, très bien, pourquoi pas...

mais je suis surpris; au début d'article, vous parlez de l'accent grave, et en fin d'article de l'accent circonflexe.

Très bien, vous utilisez un accent, mais lequel finalement ?

Perso, j'ai choisi le circonflexe ^

++
En effet, erreur d'inattention.
J'utilise bel et bien l'accent grave `

L'accent circonflexe n'est pas un bon délimiteur, car c'est un métacaractère ;)