Les expressions rationnelles avec PHP (article du Journal du Net)
Les expressions rationnelles (regular expressions,
d'où la traduction erronée "expressions régulières")
définissent des motifs (patterns) qui, en les
appliquant sur une chaîne de caractères, permettent
de tester la présence (ou non) de certains caractères,
et donc de valider cette chaîne, la modifier ou encore d'y
faire une recherche. Elles sont extrêmement puissantes
et permettent, une fois que le développeur en maîtrise
les capacités, de grandement réduire la longueur du
code: permettant ainsi de gagner du temps, mais aussi d'être
assuré de ne rien avoir oublié tant elles sont strictes.
Cet aspect des
expressions rationnelles tient au fait que le motif décrit
non-seulement le(s) caractère(s) ou la sous-chaîne
voulue, mais spécifie aussi dans quel ordre et combien
de fois les occurrences de ce(s) caractère(s) peu(ven)t apparaître.
Ainsi, si tous les utilisateurs ont un mot de passe répondant
au motif "_G347" (un tiret
de soulignement, puis une lettre majuscule, puis trois chiffres),
l'expression rationnelle correspondant à ce motif sera "^_{1}[A-Z]{1}[0-9]{3}$".
C'est ensuite aux fonctions "regex" (abréviation
usuelle pour regular expressions) de PHP de traiter ce motif
de la manière dont vous le souhaitez...
PHP propose
une poignée de fonctions en rapport avec les expressions
rationnelles, mais il faut savoir qu'elles se divisent en deux:
celles
qui sont compatibles Perl (PCRE, Perl Compatible Regular
Expression), et celles
compatibles POSIX. Le langage Perl a été l'un
des premier à faire usage des regex,
initialement développées pour l'outils Unix grep.
Perl a largement contribué à leur amélioration.
Nous ne verrons ici que celles de types POSIX, PHP devant faire
appel à une bibliothèque externe pour utiliser les
regex PCRE. Ajoutons que les deux syntaxes sont différentes
en certains points (les fonctions PCRE commencent et se terminent
obligatoirement par un caractère de délimitation),
et que les fonctions PCRE sont plus rapides et flexibles que les
POSIX.
Syntaxe
La
syntaxe de base
|
Caractère
|
Description
|
Exemple
|
^
|
Indique
le début de la chaîne
|
"^Le":
toute chaîne commençant par "Le": "Le
chiens", "Les avions"...
|
$
|
Indique
la fin de la chaîne
|
"soir$":
toute chaîne se terminant par "soir": "bonsoir",
"a ce soir"...
|
*
|
Le
caractère apparaît zéro, une ou plusieurs
fois
|
"^jim*y$":
"jiy", "jimmy", "jimmmmmmmmy"...
|
+
|
Le
caractère apparaît au moins une fois
|
"^jim+y$":
"jimy", "jimmy", "jimmmmmmmmy"...
|
?
|
La
caractère apparaît zéro ou une fois
|
"^lapins?$":
"lapin" ou "lapins"
|
{x}
|
Le
caractère apparaît strictement x fois
|
"^jim{2}y$":
"jimmy".
|
{x,)
|
Le
caractère apparaît au moins x fois
|
"^jim{2,}y$":
"jimmy", "jimmmmmy"...
|
{x,y}
|
Le
caractère apparaît entre x et y
fois
|
"^sup{1,3}e{1,9}r$":
"super", "supppeeeeeeeer"...
|
.
|
N'importe
quel caractère
|
"^P.P$":
"PHP", "PGP", "PCP"...
|
|
|
Opérateur
OU
|
"^b(a|o|u)tte$":
"batte", botte" ou "butte"
|
[xy]
|
"x
ou y" (identique à x|y)
|
"^[rmg]ite$":
"rite", "mite" ou "gite"
|
[x-y]
|
Tous
les caractères entres x et y
|
"^[a-z]{5}$":
"teejj", "dkjsh", "jfjdn", "kgodj"...
"^[a-zA-Z]{3}": une chaîne commençant par trois
lettres.
",[A-Z0-9]$": une chaîne se terminant par une virgule
suivie d'une majuscule ou d'un chiffre.
|
Ce n'est là qu'une partie de la syntaxe complète,
mais qui nous permet déjà de créer des motifs
très avancés. Pour utiliser les caractères
spéciaux ci-dessus de manière littérale, il
faut utiliser le caractère \,
sauf à l'intérieur des crochets où les caractères
spéciaux n'ont pas d'effet.
Les
fonctions POSIX sont ereg(), ereg_replace(),
eregi(), eregi_replace(),
split(), spliti()
et sql_regcase(). Le "i"
à la fin de certaines fonctions signifie simplement que ces
fonctions ne sont pas sensibles à la casse (la fonction ne
fait pas la différence entre "a" et "A",
par exemple). Florilège introductif de quelques unes de leurs
possibilités.
ereg()
et consoeurs
ereg()
est la fonction standard: elle permet de tester la présence
d'un ou plusieurs caractères dans une chaîne donnée.
Ainsi,
ereg("^_{1}[A-Z]{1}[0-9]{3}$",
$chaîne)
...renverra "TRUE" si
$chaine contient effectivement une
chaîne correspondant au motif que nous avons décrit
plus haut. Il ne reste qu'à l'implémenter dans une
structure de notre choix. Ainsi, créez une fonction is_mail()
qui va nous dire si la chaîne donné est un mail valide
syntaxiquement:
<?php
function is_mail($chaine)
{
return eregi('^[a-z0-9\._-]+@[a-z0-9\.-]+\.[a-z]{2,3}$',
$chaine);
}
?>
[a-z0-9\._-]+ nous indique qu'avant
l'arobase (@), nous acceptons un
nombre illimité (à cause de l'usage de "+")
de caractères alphanumériques (lettres et chiffres),
et les caractères ".",
"_" et "-".
Idem pour la première partie du nom de domaine, l'extension
étant pour sa part limitée à 2 à 3 caractères.
ereg_replace() et eregi_replace()
poussent la technique un peu plus loin: au lieu de dire si un motif
donné est trouvé dans une chaîne, elles remplacent
dans la chaîne les occurrences du motif, par un caractère
ou une chaîne donné en deuxième argument de
la fonction:
<?php
$chaine = "Il y a
trop d'espaces !";
$var = eregi_replace(" +", " ", $chaine);
echo $var;
?>
split(), spliti() et sql_regcase()
Ce sont là des fonctions beaucoup plus spécifiques:
split() et spliti()
décomposent une chaîne en plusieurs sous-chaînes
stockées dans un tableau. Ainsi, pour mettre chaque mot d'une
chaîne dans un tableau:
<?php
$chaine = split(" ", "Je ne sais pas quoi dire");
?>
sql_regcase(),
enfin, "prépare une expression régulière pour effectuer une
recherche insensible à la casse", c'est à dire qu'elle
construit une expression régulière qui acceptera une
motif correspondant à la chaîne spécifiée.
Par exemple, pour lancer une recherche sur une base sans avoir à
se soucier des accents ni dans la chaîne à chercher,
ni dans la base stockée:
<?php
$recherche = sql_regcase($chaine);
$recherche = ereg_replace("e", "eéèêë", $chaine);
SELECT mot FROM table WHERE champ REGEXP '$recherche';");
?>
|