Général

Les PCRE

Les POSIX

Pratique

Linux

Spécial php

Les billets de fred

Les Métacaractères dans les Expressions Régulières


Les métacaractères sont des caractères spéciaux, c'est à dire qu'ils ont une signification particulière dans la construction des motifs de recherche.
De par leur statut de caractères spéciaux, il ne peuvent pas être utilisés n'importe comment.
Si on se base sur la doc php, ces caractères spéciaux ou métacaractères sont les suivants:

^ . [ ] $ ( ) * + ? | { } \


Jusque là, je suis entièrement d'accord, ce sont bien tous des métacaractères, tant pour les POSIX que pour les PCRE.

Par contre, il en est de ceux dont on ne parle jamais, de ceux qui semblent avoir été oubliés ou laissés sur le côté. Ils sont au nombre de 5 et n'interviennent que dans le cas des PCRE.

On trouvera dans cette catégorie :
  • le point d'exclamation
  • les chevrons ouvrant et fermants
  • le signe égal (=)
  • le deux-points (:)
! < > = :


Mais qu'est ce qu'il nous raconte encore, on n'a jamais entendu parler de ça nous !

Bon je vois bien que vous ne me croyez pas, mais c'est pas grave on va y revenir par la suite.

Par contre, comme vous le savez déjà, ou du moins vous devriez le savoir, je l'ai dit, en plus, dans "Créer un motif" (>>> cf->Créer un motif), ces caractères spéciaux perdent leur statut s'ils sont utilisés entre les crochets [ ] donc, à l'intérieur d'un classe.
Vous savez également que pour enlever le statut de métacaractère en dehors de la classe, il suffit d'utiliser l'antislash \. Un exemple vaut mieux qu'un long discours.

Exemple : $chaine='Je cherche un crochet ouvrant [ dans cette phrase';
// avec les PCRE
if(preg_match('`[`',$chaine)){echo'TRUE';}else{echo 'FALSE';}
// avec les POSIX
if(ereg('[',$chaine)){echo'TRUE';}else{echo 'FALSE';}
?>
On aura droit à un beau message d'erreur !

Pour preg_match() il sera du style :
Warning: preg_match() [function.preg-match]: Compilation failed: missing terminating ] for character class at offset 1 in...
Pour ereg() il sera du style :
Warning: ereg() [function.ereg]: REG_EBRACK:cbrackets ([ ]) not balanced in...

Tout le monde suit, c'est très bien !

On va changer notre exemple et utiliser un antislash :
$chaine='Je cherche un crochet ouvrant [ dans cette phrase';
// avec les PCRE
if(preg_match('`\[`',$chaine)){echo'TRUE';}else{echo 'FALSE';}
// avec les POSIX
if(ereg('\[',$chaine)){echo'TRUE';}else{echo 'FALSE';}
?>
Magnifique, plus de message d'erreur, tout fonctionne !

Règle générale:


Pour utiliser un métacaractère dans le motif d'une regex, il faut le faire précéder d'un antislashe \ sauf s'il est utilisé dans une classe de caractères.
Et voilà, tout est dit !

Et bien non, tout n'est pas dit justement.

Exceptions:


Le crochet fermant et le tiret gardent leur statut de métacaractère dans une classe.
Par contre en dehors de la classe, chacun d'eux est un simple littéral.

On va chercher un crochet fermant par exemple : $chaine='Je cherche un crochet fermant ] dans cette phrase';

if(preg_match('`]`',$chaine))
{
echo'TRUE';
}else{
echo'FALSE';
}
?>
Et voilà, ça fonctionne très bien en dehors de la classe !

Pire, ça fonctionne aussi dans une classe : $chaine='Je cherche un crochet fermant ] dans cette phrase';

if(preg_match('`[]]`',$chaine))
{
echo'TRUE';
}else{
echo'FALSE';
}
?>

Mince, mince, mince, mince..., ça devient vachement compliqué là, comment doit-on faire alors ?

Etudions la regex suivante :

$motif='`[][(){}-]`';

preg_match ($motif,$chaine);
?>

Analyse du motif :
Lors de l'interprétation et de l'analyse de ce motif, le moteur de regex va rencontrer un premier crochet ouvrant [ qu'il va considérer comme un caractère spécial puisque, n'étant pas précédé par un antislash, il définit l'ouverture d'une classe de caractères.

Logique jusque là, on le sait déjà ça !

Vient ensuite le crochet fermant ]. Là, le moteur d'expressions régulières va simplement le considérer comme un caractère normal car : une classe vide n'est pas reconnue par le moteur de regex.

Ensuite, nous retrouvons un crochet ouvrant [ qui sera lui aussi considéré par le moteur de regex comme caractère normal puisque la classe est déjà active avec le premier crochet ouvrant.

Viennent les parenthèses, les accolades et enfin en dernière position, on place le tiret.
Ce fameux tiret qui à l'intérieur d'un classe indique au moteur une plage de recherche comme dans [0-9]

On termine enfin avec le crochet fermant qui signale au moteur d'expressions régulières la fermeture de la classe. Et voilà, le moteur aura analysé tous les caractères entre crochets comme des littéraux.


Voilà, vous savez maintenant comment se comportent les métacaractères habituels.

Mais revenons en arrière et intéressons nous aux 5 autres qui ne sont pas considérés par la Doc officielle (Php) comme étant des métacaractères.
Dans le travail avec les POSIX, ces 5 symboles n'avaient d'ailleurs aucune raison d'être assimilés à des caractères spéciaux, puisqu'ils étaient utilisés comme simples littéraux.

Par contre avec les PCRE, il n'en est pas de même et ces 5 caractères sont utilisés dans les assertions.
Les assertions sont des sous-masques qui permettent de vérifier certaines conditions. Pour créer ces assertions, l'emploi des 5 caractères est impératif et ils ont dans cette position un statut spécifique qui les assimile à ce moment précis à des métacaractères.

Ah la vache..., voilà qu'il recommence avec ses explications à la 6-4-2 !
Mais qu'est ce qu'il nous raconte là ?

Je ne vais pas vous développer le sujet ici et je vais vous renvoyer vers les tutos sur les assertions ainsi que sur l'article parlant du choix du délimiteur de PCRE.

Cf->Les assertions I     Cf->Les assertions II     Cf->Le délimiteur et les PCRE
ADAM Benjamin 2008 | Admin