Expressions Régulières (RegExp)

Les expressions régulières permettent de faire des comparaisons avancées au niveau des chaînes de caractères ou d'en extraire aisément certaines parties.

Les regexp seront indiquées entre barres de divisions (/ma regexp/). Il existe deux types de regexp : les regexp "POSIX" et les regexp "PERL". Le langage PHP a choisi de se concentrer sur les regexp PERL plus complètes et les regexp POSIX ont été dépréciées.

En fin de regexp, on peut placer des options. Les deux options les plus utiles sont i (case Insensitive) et u (UTF-8). Dans les exemples ci-dessous, ces options sont absentes. Il faudra donc utiliser du texte ASCII (caractères non accentués entre autres).

Texte

Si on désire faire reconnaître un texte, il suffira de le mettre tel quel. Ainsi, une regexp /ABC/ reconnaîtra toute chaîne contenant la séquence ABC (où qu'elle se trouve).

Le texte sera vérifié "case sensitive". Les majuscules seront considérées comme différentes des minuscules.

On peut utiliser ainsi la plupart des caractères, à l'exception des caractères ayant une signification spéciale dans les regexp.

Caractères spéciaux

Le caractère ^ indique le début de la chaîne. Il "ancre" la regexp en début de chaîne au lieu de permettre de la placer n'importe où dans la chaîne (par exemple, /^A/ indique les chaînes qui commencent par un A (Albert, Arbre, Alchimie). Le A doit se trouver impérativement au début et donc un mot comme BANANE ne sera pas valide)

Le caractère $ indique la fin de la chaîne. Il "ancre" la regexp en fin de chaîne (par exemple /GIF$/ indiquera que la chaîne doit se TERMINER par GIF (Logo.GIF)). Si on utilise en même temps ^ et $, la regexp sera ancrée aux deux extrémités et la chaîne complète doit correspondre à la regexp (par exemple, /^B+$/ acceptera B, BB, BBB mais pas AB ou BC)

Le caractère . remplace n'importe quel caractère (Par exemple, /A.B/ acceptera A0B, A1B, AAB, ABB, ACB, AXB mais n'acceptera ni AB (il manque un caractère entre A et B) ni AZZB (il y a 2 caractères au lieu d'un)

Certains caractères ont une signification spéciale au niveau des regexp. Si on désire les faire apparaître dans leur signification normale, il est nécessaire de les précéder d'un \.

Les caractères + * ? . ( ) [ ] / | { } ^ $ et \ doivent être précédés d'un \ (par exemple \$, \[, ...).

ATTENTION, dans une chaîne PHP, le caractère \ a lui-même une signification spéciale et devra être doublé

Répétitions (1)

Le caractère * permet d'indiquer que l'élément (caractère ou autre) qui précède est répété zéro ou plusieurs fois. En d'autres termes, /A*/ indique que l'on aura une séquence de 0, 1, 2 ou plus fois la lettre A (par exemple rien, A, AA, ...). /AB*C/ indiquera un A suivi de 0 ou plus fois B et enfin un C, le tout collé ensemble (par exemple AC, ABC, ABBC, ...)

Le caractère + permet d'indiquer que l'élément qui précède est répété 1 ou plusieurs fois. Contrairement à *, l'élément DOIT être présent (par exemple, /AB+C/ acceptera ABC, ABBC, ABBBC mais pas AC).

Le caractère ? indique que l'élément qui précède peut être présent 0 ou 1 fois (par exemple /AB?C/ acceptera AC et ABC)

L'élément qui précède *, + ou ? peut être juste un caractère ou peut être un élément plus compliqué tel que décrit plus loin. /A.+B/ considérera qu'on a un ou plusieurs . (caractère quelconque) et donc, les caractères entre A et B pourront être différents.

Répétitions (2)

On peut également indiquer une répétition en utilisant {min,max} (par exemple, /A{4,6}/ indique qu'il faut 4, 5 ou 6 A qui se suivent.

{min,} ou {,max} permettent de n'indiquer que le minimum ou le maximum. {nombre} permet d'indiquer le nombre exact (Par exemple, /A{4}/ est similaire à /AAAA/ et /.{3}/ à /.../)

Groupes et Alternatives

Les parenthèses permettent de marquer une sous-partie de regexp. Les opérateurs de répétition s'appliqueront à l'ensemble mis entre parenthèses (par exemple, /^(BA)+$/ acceptera BA, BABA, BABABA, ... mais pas BAAAA, le + s'applique à l'entièreté de ce qui est mis entre parenthèses)

L'opérateur | permet de préciser une alternative. Il sépare deux expressions régulières. (Par exemple, /^Hello|Goodbye$/ acceptera Hello et Goodbye mais pas Hellooobye ou HellGoodbye)

Les parenthèses permettent aussi "d'arrêter" l'alternative. Si l'alternative est située dans les parenthèses, elle se limite aux morceaux situés dans ces parenthèses (par exemple, /^(Hello|Goodbye) World$/ acceptera Hello World et Goodbye World).

A noter que les parenthèses ont également d'autres utilités qui seront vues plus loin.

Classes (1)

On peut indiquer un ensemble de caractères acceptables en les mettant dans des [ ]. Les caractères sont pris dans l'ordre ASCII et les seuls caractères spéciaux dans une classe sont ^, - et ] (Par exemple, [123] veut dire un des caractères 1, 2 ou 3

Si la classe est suivie d'un opérateur de répétition, chaque répétition pourra avoir une valeur différente dans la classe (Par exemple, [ABC]+ contiendra une série de caractères A, B et C comme AB, AAA, CCCBBBAAA, ABACABCCB, ...)

On peut également spécifier deux caractères séparés par un -, dans ce cas, tous les caractères situés (dans l'ordre ASCII) entre ces deux caractères sont également inclus (par exemple, [a-z] représente toutes les lettres minuscules (non accentuées).)

Si le premier caractère de la classe est ^, il "inverse" la classe. Seuls les caractères qui ne sont PAS dans la liste seront acceptés (par exemple, [^()] indique tous les caractères sauf les parenthèses). Si le ^ se trouve ailleurs, il perd sa signification spéciale

Si on met un - en début ou en fin de classe (pas entre deux caractères), il perd sa signification spéciale. On le mettra généralement en fin de classe (pour laisser la première place à un éventuel caractères ^).

Classes (2)

Les séquences reprises dans la table ci-dessous représentent certaines classes de caractères fréquents. Elles peuvent être utilisées soit directement dans une regexp, soit à l'intérieur d'une classe à côté d'autres caractères (par exemple, \d\d représente 2 chiffres qui se suivent et [\dA-F] représente un caractère hexadécimal (chiffre ou lettre de A à F)).

SéquenceCaractères
\dChiffre
\DPas un chiffre
\sCaractère blanc (espace, tabulation, ...)
\SCaractère non blanc
\wCaractère de "mot" (lettre, chiffre et _)
\WCaractère qui ne fait pas partie d'un mot)

D'autres classes utilisent la notation POSIX. Attention, cette notation n'est pas toujours supportée (par exemple, elle n'est pas supportée en Javascript). Ces classes sont reprises dans la table ci-dessous. Le support des accents n'est pas garanti.

SéquenceCaractères
[:alnum:]Lettres et Chiffres
[:alpha:]Lettres majuscules ou minuscules
[:ascii:]Caractère dont le numéro est entre 0 et 127
[:blank:]espace ou tabulation
[:cntrl:]Caractères de contrôle (0-31)
[:digit:]Chiffres (\d)
[:lower:]Lettre minuscule (a-z)
[:punct:]Caractère de ponctuation
[:upper:]lettre Majuscule (A-Z)
[:word:]Caractère de mot (\w)
[:xdigit:]Caractère hexadécimal

Il est préférable d'éviter les séquences POSIX autant que possible et leur préférer soit une énumération de caractères (par exemple 0-9A-Za-z pour [:alnum:]), soit la forme \x (quand elle existe), soit la classe UTF-8 (si la regexp est en mode UTF-8)

Classes (3)

Ce qui suit ne fonctionne que su l'option u (utf-8) a été fournie et si l'encodage des chaînes (aussi bien la regexp que la chaîne analysée) est en UTF-8

Chaque caractère unicode possède une catégorie principale représentée par un code de 2 lettres. On peut spécifier un caractère de cette catégorie à l'aide de \p{xx} ou un caractère qui ne fait pas partie de cette catégorie à l'aide de \P{xx} ou \p{^xx} (la première forme est préférée).

Les principales catégories sont reprises dans la table ci-dessous.

CategorieSignification
LLettre
LlLettre minuscule (lowercase)
LmLettre "modificateur" (ajout d'un "accent" à une autre lettre par exemple)
LoLettre Autre
LuLettre majuscule (uppercase)
NNombre
NdNombre Décimal
NlNombre lettre
NoNombre Autre
PPonctuation
PcPonctuation de connexion (tiret dans un mot composé par exemple)
SSymbol
ScSymbole monétaire (Currency)
SmSymbole Mathématique

On peut aussi utiliser \p{Langue} pour détecter les caractères liés à une langue particulière. Quelques alphabets reconnus sont Arabic, Braille, Cyrillic, Devanagari, Greek, Han, Hangul, Hebrew, Hiragana, Katakana, Latin, Thai, ... (Han correspond aux caractères Chinois).

Attention, dans certains langages (dont le Javascript), il faut préciser qu'on teste la langue en préfixant par Script=, Script_Extension= ou la forme abrégée sc=. En PHP, ce préfixe ne doit pas être présent.

Prédicats

Tout comme ^ et $ représentent des positions (début et fin) dans la chaîne sans pour autant représenter des caractères eux-même, d'autres séquences permettent de préciser du contexte sans que ce dernier ne soit repris dans le texte matché en lui-même.

Ainsi, \b représente une transition entre un caractère "mot" \w (lettre, chiffre ou _) et un caractère non mot (ponctuation, caractères blancs, début ou fin de chaîne, ...). Il permet ainsi de vérifier qu'une séquence de caractères représente un mot et pas un morceau de mot (/\bchier\b/ matchera "chier" mais pas "fichier")

Il est aussi possible d'indiquer un texte (sous forme de regexp) devant apparaître avant ou après le texte que l'on cherche à matcher (fournir un contexte) sans qu'il ne fasse partie du texte matché.

Les assertions peuvent tester plusieurs fois le même texte (suivi de ... mais pas de ...). Le texte matché par le prédicat n'est pas "consommé" dans la chaîne.

(?=texte)Texte qui doit suivre
(?!texte)Texte qui ne doit pas suivre
(?<=texte)Texte qui doit précéder
(?texte)Texte qui ne doit pas précéder

Capture et référence

Chaque fois que l'on utilise les parenthèses, non seulement on groupe une partie de regexp en un morceau, mais en plus, on la capture. Les expressions capturées peuvent être utilisées dans le langage qui traite la regexp (sauvées dans un tableau par exemple) ou elles peuvent être utilisées dans la regexp, pour indiquer qu'un texte doit être répété (par exemple pour des balises [h1]...[/h1])

Si on désire éviter la capture, il faut remplacer les parenthèses par le forme (?:...) qui effectuera le regroupement mais pas la capture.

Dans une regexp, pour rappeler un texte capturé, on utilisera \\ suivi d'un nombre. Les valeurs de 1 à 9 seront toujours interprétées comme des références, les valeurs 10 et plus ne le seront que si il y a eu assez de captures (\\12 ne sera considéré comme une référence que si il y a eu 12 captures ou plus).