Une fois n'est pas coutume, il y a peu de fonctions concernant les expressions régulières dans PHP. Ces fonctions, au nombre de sept, peuvent être classées en trois groupes :
Les fonctions pour la recherche de correspondance vérifient si une chaîne est conforme ou non à une expression régulière. Il y a deux fonctions dans cette catégorie, qui permettent non seulement de vérifier la correspondance d'une chaîne à un motif, mais également de récupèrer les parties correspondantes aux motifs.
La fonction preg_match() est sans doute la plus utilisée de toutes les fonctions d'expression régulière. Elle permet d'abord de vérifier qu'un modèle est trouvé dans une chaîne. Le modèle est le premier paramètre de la fonction, et la chaîne le deuxième. La fonction renvoie TRUE si le modèle est trouvé, FALSE sinon.
L'exemple suivant utilise la fonction preg_match() pour définir si une chaîne correspond au modèle d'une adresse e-mail.
L'exemple suivant teste différents formats de nombres.
Si notre expression régulière contient des sous-chaînes (définies par des parenthèses ouvrantes et fermantes), la fonction preg_match() peut être utilisée avec un troisième paramètre : le nom d'un variable qui contiendra après exécution de la fonction les captures effectuées. Les sous-chaînes répondant au modèle seront capturées, et renvoyées sous la forme d'un tableau.
Reprenons l'expression qui sert à valider une adresse e-mail :
/^[a-z][\w\-\.]*@[a-z][\w\-\.]*\.[a-z]{2,6}$/i
Cette expression peut être séparée en plusieurs parties :
Si nous entourons la partie locale, la partie nom de domaine et la partie grand domaine par des parenthèses, nous pouvons récupèrer ces zones sous la forme d'éléments de tableau.
Essayons donc cette expression régulière :
/^([a-z][\w\-\.]*)@([a-z][\w\-\.]*)\.([a-z]{2,6})$/i
Le résultat du test montre le tableau créé par la fonction preg_match() dans la variable $t. Le premier élément du tableau est le texte capturé entier. Les éléments suivants sont les différentes sous-chaînes.
Nous pouvons enlever les assertions de début et fin de chaîne pour
travailler sur un texte plus complet comme :
"Vous pouvez
écrire à francois.piat@univ-fcomte.fr pour féliciter l'auteur de ce
cours."
Que se passe-t-il quand le texte à examiner est le suivant :
"Vous pouvez écrire à francois.piat@univ-fcomte.fr ou à
fpiat@femto-st.fr pour féliciter l'auteur de ce cours.".
Nous avons ici deux adresses email, et on devrait avoir le tableau
suivant :
|
Indice |
Valeur |
|
0 |
francois.piat@univ-fcomte.fr |
|
1 |
francois.piat |
|
2 |
univ-fcomte |
|
3 |
fr |
|
4 |
fpiat@femto-st.fr |
|
5 |
fpiat |
|
6 |
femto-st |
|
7 |
fr |
Le résultat du test n'est pas celui que nous attendons. Le tableau ne montre que la première adresse email trouvée. Le code n'est pas en cause et fonctionne parfaitement. En effet, la fonction preg_match() s'arrête à la première occurence trouvée pour le modèle. Pour récupèrer toutes les occurences su modèle, il faut utiliser une autre fonction.
La fonction preg_match_all() fonctionne comme preg_match() à la différence qu'elle recherche le modèle autant de fois que c'est possible, et qu'elle ne s'arrête pas à la première concordance trouvée.
Après l'exécution de la fonction, la variable utilisée pour stocker le résultat contiendra un tableau à deux dimensions, classé par correspondance ou par ordre des parenthèse selon la valeur du quatrième paramètre de la fonction preg_match_all(). Vous n'avez rien compris ? Alors passez aux exemples.
Comme le montre le test, l'utilisation de la constante prédéfinie PREG_SET_ORDER offre ici le meilleur moyen pour traiter au mieux les résultats de la fonction preg_match_all().
Affichez la liste des liens inclus dans la page à l'adresse http://www.php.net (vous devez avoir une connexion Internet ouverte). Afficher simplement la liste avec la fonction print_r() ou avec la fonction infoTableau() comme dans les exemples du cours.
La fonction file_get_contents vous permet de récupérer le contenu d'un fichier. Par exemple :
$codeHTML = file_get_contents('http://www.php.net');
Rappel : un lien est la valeur de l'attribut href.
Une première solution toute simple.
Cette première solution capture absolument tous éléments liés, même ceux qui ne sont pas des liens cliquables (feuilles de styles par exemple). En plus, la valeur de l'attribut href doit être entourée avec des guillemets doubles, ce qui n'est pas toujours le cas.
Nous pouvons améliorer l'expression comme ça :
<a[\s]+[^>]*?href[\s]?=[\s\"\']+(.*?)[\"\']+.*?>/is
| <a | la chaîne littérale <a |
| [\s]+ | 1 ou plusieurs caractères d'espacement |
| [^>]*? | n'importe quel caractère sauf un >, non gourmand |
| href | la chaîne littérale href |
| [\s]? | 0 ou plusieurs caractères d'espacement |
| = | la chaîne littérale = |
| [\s\"\']+ | 1 ou plusieurs caractères d'espacement ou " ou ' |
| (.*?) | n'importe quel caractère n'importe combien de fois, capturé |
| [\s\"\']+ | 1 ou plusieurs caractères d'espacement ou " ou ' |
| .*? | n'importe quel caractère n'importe combien de fois, non gourmand |
| > | la chaîne littérale > |
| i | ignore la casse |
| s | le point reconnaît les sauts de ligne |