Général

Les PCRE

Les POSIX

Pratique

Linux

Spécial php

Les billets de fred

Les assertions... simples ! (Partie I)


Pour rappel, les motifs sont réalisés au moyen de symboles spécifiques que vous trouverez sur cette page : Cf-> Les Symboles

Dans cette partie de cours, nous allons aborder le premier chapitre sur les assertions en commençant par ce qui semble être le plus évident, à la question que chacun se pose :

Une assertion... qu'est ce que c'est ?

Sans le savoir jusqu'à présent, vous vous êtes servis des "assertions simples", et ce, depuis le début de votre apprentissage en utilisant les caractères de début et fin de chaîne, soit les caractères ^ et $.

Si je devais donner une définition de l'assertion, je dirais : L'assertion doit être considérée comme une "condition spécifiée" à un certain endroit dans la recherche et elle agit comme un test sur les caractères suivants ou précédents celui qui est en cours d'analyse.
Elle peut être positive ou négative, ne remplace et ne consomme aucun caractère.

Piouuuu la vache..., mais qu'est ce qu'il dit ?
Ouhlala, passez-moi les aspro !

Un exemple valant mieux qu'un long discours, on va commencer avec des exemples d'assertions simples.

1) Le ^ et le $... des assertions simples ? Oui !

Condition : Doit débuter par...$chaine='les expressions régulières';
if(preg_match('`^[a-z]`',$chaine))
{
echo'Vrai, la chaîne commence par une lettre.';
}
else
{
echo'Faux, la chaîne ne débute pas par une lettre';
}
?>

La condition est :

- la chaîne doit commencer par un caractère alphabétique compris entre a et z.

En reprenant notre motif précédent, il suffit simplement de mettre le symbole $ après les crochets pour imposer la condition : doit se terminer par...

Condition : Doit finir par...if(preg_match('`[a-z]$`',$chaine))
{
echo'Vrai, la chaîne se termine bien par une lettre.';
}
else
{
echo'Faux, la chaîne ne se termine pas par une lettre';
}
?>

2) Les assertions simples... les autres !

Vous l'avez vu, du moins tous ceux qui ont lu >>> Les ancrages et classes génériques, certains caractères spécifiques sont considérés comme des ancrages. Ce sont des assertions simples et sont codées au moyen des caractères : \b - \B - \A - \Z et \z

\b indique une limite de mot dans une chaîne de caractères.
\B indique ce qui n'est pas une limite de mot.
\A agit comme le ^ sur le début de la chaîne sujet, hormis le fait que \A est indépendant du mode multi-lignes.
\Z et \z agissent comme le $ sauf qu'ils sont indépendants du mode multi-lignes et que :
\Z recherche les positions avant les nouvelles lignes et à la fin de la chaîne sujet, tandis que \z ne recherche que la fin de la chaîne sujet.

A noter, je le répète, ce type d'assertion (ancrage) ne consomme pas de caractère. Vous allez voir dans le développement de l'exemple qui suit, l'emploi et l'utilité de la limite de mot \b

Les assertions simples... un peu moins simples !

Je viens de le dire deux lignes plus haut, les assertions ne "mangent" pas de caractères et sont donc "non-consommatrices".
Pour bien comprendre ce que représente la "non-consommation de caractère", on va se baser sur un exemple très simple.

Considérons la phrase suivante :

C'est bon, voilà une bonne phrase contenant des bons mots comme bonnet, rebondir et bonbons.
Le but recherché : sortir l'adjectif bon (ou bons au pluriel) de la phrase.

Bah... facile, tout simple, j'ai besoin de preg_match_all pour faire ça ! preg_match_all('`bons?`', $ma_phrase, $out);

print_r($out[0]);

?>

Résultat du print_r() :
Array
(
   [0] => bon
   [1] => bon
   [2] => bon
   [3] => bons
)

Ah... zut, il me sort 7 occurrences du mot "bon" au singulier ou au pluriel !

Réfléchissons un peu !

Bah ça y est... je recommence en mettant un espace de chaque côté de mon mot à trouver ! preg_match_all('` bons? `', $ma_phrase, $out);

print_r($out[0]);

// Résultat du print_r() :
// Array ( [0] => bons )
?>
Ah... re-zut , il m'en sort plus qu'un seul là et au pluriel seulement, j'ai pas le premier à cause de la virgule !

Pas grave, on va ajouter la ponctuation dans le masque et ça va le faire ! preg_match_all('` bons?[ .,:;!]`', $ma_phrase, $out);

print_r($out[0]);

// Résultat du print_r() :
// Array ( [0] => bon, [1] => bons )
?>
Ah... aaaaaah , il me sort ce que j'ai demandé, impec !
Euh... non, pas tout à fait en somme, j'ai pas besoin de cette virgule après "bon" et de cet espace inutile avant "bons"!

Héhé, je vais matcher avec des parenthèses capturantes comme ça j'aurais ce que je veux !
preg_match_all('` (bons?)[ .,:;!]`', $ma_phrase, $out);

print_r($out[1]); // j'ai changé le [0] par [1] qui contient le résultat de la parenthèse capturante

// Résultat du print_r() :
// Array ( [0] => bon, [1] => bons )
?>
Impec là, ça le fait bien !

Bah oui, mais l'assertion simple là-dedans, elle est où ?
Elle arrive !
Je vous l'ai dit plus haut, une assertion ne consomme pas de caractère, donc pas de ressource.
Hors, notre solu avec parenthèses capturantes n'est pas forcément la meilleure puisqu'elle utilise de la ressource.

C'est ici qu'intervient notre assertion simple, la limite de mot \b.
preg_match_all('`\bbons?\b`', $ma_phrase, $out);

print_r($out[0]);

// Résultat du print_r() : Array ( [0] => bon [1] => bons )
?>
Et voilà, le même résultat que précédemment, mais sans consommation de mémoire et surtout 3 à 4 fois plus rapidement que toutes les autres formes de syntaxe précédente.

La suite, c'est par là : >>> Les Assertions Part II
ADAM Benjamin 2008 | Admin