I. Pré-requis▲
Pour comprendre cet article, vous devez savoir programmer en JavaScript et connaître les bases du langage, à savoir délarer et modifier une variable, récupérer une partie d'une chaîne de caractères, etc.
II. Découverte▲
II.1. Introduction▲
Si vous avez déjà ouvert un fichier JavaScript d'un autre développeur, vous avez peut-être déjà vu un code similaire au suivant :
if
(
!
pseudo.
match
(
/
^
(
[
a-
zA-
Z ]
+
)$/
))
alert
(
'
Pseudo
invalide
'
);
Ce petit bout de code /^([a-zA-Z ]+)$/ se nomme regex, ou expression régulière. Cela permet, entre autre, de vérifier le contenu d'une chaîne de caractères.
II.2. POSIX et PCRE▲
Vous avez peut-être déjà vu apparaître ces deux termes au cours d'une discussion entre développeurs ou tout simplement dans un article. Il s'agit des deux grands types de regex que l'on retrouve dans pas mal de langages de programmations.
Si vous avez déjà fait du Perl, vous avez peut-être déjà utilisé les regex PCRE. Si vous avez déjà fait du PHP, vous avez soit fait des regex POSIX, soit PCRE, puisque les deux sont supportés par PHP.
En JavaScript, seules les regex PCRE sont supportées (comme Perl) !
II.3. Définir une expression régulière▲
Pour définir une expression régulière, il faut la placer entre deux slashs (/), et peut être placée dans une variable, comme ceci :
var
regex =
/
leContenuDeMaRegex/
;
Les chaînes de caractères sont définies entre guillemets ('), les regex entre des slashs (/) !
II.4. Contexte d'utilisation▲
Une regex peut être utilisé via deux méthodes :
- soit en utilisant la fonction match() que nous allons voir tout de suite ;
- soit en utilisant l'objet RegExp que nous aborderons un peu après.
II.4-A. La fonction String.match()▲
Lorsque vous utilisez une chaîne de caractères, vous pouvez lui appliquer la fonction match(), de la manière suivante :
var
message =
'
Bonjour
les
gens
!
'
;
var
regex =
/
les/
;
if
(
message.
match
(
regex))
alert
(
'
Tiens,
il
y
a
plusieurs
personnes
?
'
);
else
alert
(
'
Tout
seul...
'
);
Si vous exécutez ce code, vous obtiendrez une alerte "Tiens, il y a plusieurs personnes ?". En effet, la regex /les/ vérifie que "les" est présent au moins une fois dans la chaîne de caractère message (qu'on peut appeler sujet de l'expression régulière).
Notez que j'aurais très bien pu écrire le code de cette manière :
var
message =
'
Bonjour
les
gens
!
'
;
if
(
message.
match
(
/
les/
))
alert
(
'
Tiens,
il
y
a
plusieurs
personnes
?
'
);
else
alert
(
'
Tout
seul...
'
);
C'est vraiment similaire aux chaînes de caractères.
II.4-B. L'objet RegExp▲
Vous pouvez aussi utiliser l'objet RegExp pour créer des expressions régulières. Dans ce cas, la fonction match() fonctionnera très bien aussi.
var
message =
'
Bonjour
les
gens
!
'
;
var
regex =
new
RegExp
(
'
les
'
);
if
(
message.
match
(
regex))
alert
(
'
Tiens,
il
y
a
plusieurs
personnes
?
'
);
else
alert
(
'
Tout
seul...
'
);
Vous voyez que j'ai juste créé un objet RegExp. Notez qu'il n'y a pas besoin d'écrire les / lorsque l'on utilise l'objet RegExp. Cela permet (notamment) de créer une regex à partir d'une chaîne de caractères.
Par exemple, le code suivant ne peut fonctionner qu'à partir d'une RegExp :
var
prompt_regex =
prompt
(
'
Votre
regex
?
'
,
'
'
);
var
prompt_message =
prompt
(
'
Votre
message
?
'
,
'
'
);
var
regex =
new
RegExp
(
prompt_regex);
if
(
prompt_message.
mach
(
prompt_message))
alert
(
'
La
regex
a
trouvé
quelque
chose
!
'
);
else
alert
(
'
La
regex
n
'
a rien trouvé ;
-
(
'
);
Car en effet, vous ne pouvez pas écrire :
var
regex =
//
+
prompt_regex;
Cela génèrera une erreur.
II.4-C. Les différents caractères spéciaux des regex▲
Les regex utilisent des caractères spéciaux pour pouvoir chercher plus facilement une information dans une chaîne de caractères. Et leur but est de vous faire gagner du temps et du code.
La preuve, si vous voulez que l'utilisateur saisisse un code, et que vous voulez que celui-ci soit bien constitué uniquement de 4 chiffres, vous devrez effectuer le code suivant sans regex :
var
code =
prompt
(
'
Le
code
svp
?
'
,
'
'
);
var
error =
false
;
for
(
var
i =
0
;
i <
4
;
i+
+
)
if
(
!
code[
i]
=
=
'
0
'
|
|
!
code[
i]
=
=
'
1
'
|
|
!
code[
i]
=
=
'
2
'
|
|
!
code[
i]
=
=
'
3
'
|
|
!
code[
i]
=
=
'
4
'
|
|
!
code[
i]
=
=
'
5
'
|
|
!
code[
i]
=
=
'
6
'
|
|
!
code[
i]
=
=
'
7
'
|
|
!
code[
i]
=
=
'
8
'
|
|
!
code[
i]
=
=
'
9
'
) {
error =
true
;
break
;
}
if
(
!
error)
alert
(
'
Le
code
semble
correct...
'
);
else
alert
(
'
Mauvais
format
de
code
!
(4
chiffres)
'
);
Et voici ce que ça donne avec une regex :
var
code =
prompt
(
'
Le
code
svp
?
'
,
'
'
);
var
error =
false
;
if
(
!
code.
match
(
/
^
(
[
0
-
9
]
){
4
}
$/
))
alert
(
'
Le
code
semble
correct...
'
);
else
alert
(
'
Mauvais
format
de
code
!
(4
chiffres)
'
);
Avouez qu'on gagne quand même à utiliser des regex, hein ? :-) Et c'est encore pire pour vérifier une adresse e-mail, par exemple !
Analysons ensemble cette regex.
- Le ^ indique que la chaîne de caractères doit commencer par ce qui est marqué après.
- Le $ indique que la chaîne de caractères doit se terminer par ce qui est marqué avant.
Vous l'aurez compris, une regex entourée d'un ^ et d'un $ signifie que toute la chaîne de caractères doit correspondre. Par exemple, "les gens" fonctionne avec /les/, avec /^les/, mais pas avec /^les$/ ou même /les$/.
- Les caractères situés entre les deux crochets [ et ] permettent de dire "n'importe quoi mais qui est marqué entre ces crochets". Par exemple, [0-9] veut dire "n'importe quel chiffre", [abc] veut dire "la lettre a, la lettre b ou la lettre c". On peut utiliser dans une regex : 0-9 : un chiffre ;a-z : une lettre minuscule ;A-Z : une lettre majuscule ;ou des caractères indépendants, comme [abc].
- Les parenthèses permettent de spécifier son contenu comme une donnée de la regex. On verra ça plus tard, ne vous inquiétez pas.
- Un chiffre entre crochets permet de dire "ce qu'il y a avant, répété x fois". Par exemple, ([0-9]){4} signifie "un chiffre, répété 4 fois", soit 1456, 1795, 7513, etc. On peut également dire "au moins 4 fois" si le code fait minimum 4 chiffres, en écrivant ([0-9]){4,}. Ou encore "2 à 4 fois" avec ([0-9]){2,4}.
Vous voyez, les expressions régulières sont vraiment très utiles lorsqu'il s'agit de vérifier le contenu d'une chaîne de caractères !
Comprendre les regex n'est pas chose facile, si vous n'avez pas tout compris, n'hésitez pas à relire cette partie du cours !
Les répétitions
Si vous voulez que la chaîne de caractères donnée contienne "il y a x personnes" (il y a 8 personnes, il y a 45 personnes, etc.), vous ne pouvez pas seulement utiliser un ([0-9]). Vous devez vérifier qu'il y a au moins un chiffre, sinon plusieurs. La solution que nous avons vue est de faire :
/
^
il y a (
[
0
-
9
]
){
1
,
}
personnes$/
Mais on peut le faire encore plus facilement en utilisant un opérateur avant la parenthèse fermante :
/
^
il y a (
[
0
-
9
]
+
) personnes$/
Le + permet de dire "au moins une fois", il "remplace" le {1,} (en fait c'est plus complexe que ça, mais nous le verrons plus tard). Si j'avais mis un ?, ça aurait voulu dire "optionnel", c'est-à-dire soit 0 fois, soit 1, soit 2, etc. Il "remplace" le {0,}
II.4-D. Un p'tit T.P. ?▲
1) Sujet
Voyons voir si vous avez bien tout compris ! Vous allez devoir créer une regex qui permet de vérifier que le pseudo saisit par l'utilisateur contient bien des chiffres, des lettres ou des tirets bas, et fait de 6 à 20 caractères de long. A vos marques, prêts, codez !
Ne lisez pas la suite du cours à moins de ne pas du tout réussir à créer cette regex !
2) Correction
Tout d'abord, nous devons vérifier que le pseudo contient des lettres, des chiffres ou des tirets bas (_). On fait donc :
(
[
0
-
9a-
zA-
Z_]
)
Maintenant, il faut qu'il mesure entre 6 et 20 caractères, donc :
(
(
[
0
-
9a-
zA-
Z_]
){
6
,
20
}
Enfin, il doit être UNIQUEMENT composé de cela, donc commencer et termine par notre regex :
^
(
[
0
-
9a-
zA-
Z_]
){
6
,
20
}
$
Et le code final :
var
pseudo =
prompt
(
'
Votre
pseudo
?
'
,
'
'
);
if
(
pseudo.
match
(
/
^
(
[
0
-
9a-
zA-
Z_]
){
6
,
20
}
$/
))
alert
(
'
Pseudo
correct
!
'
);
else
alert
(
'
Pseudo
incorrect
;-(
'
);
III. Utilisation des regex pour remplacement▲
III.1. Remplacement basique et flags▲
En JavaScript, vous pouvez utiliser la fonction replace() sur les chaînes de caractères. Celle-ci prend en paramètres une regex, et la valeur de remplacement.
Prenons un exemple simple :
var
message =
'
Salut
Michel
'
;
alert
(
message.
replace
(
/
Michel/
,
'
Antoine
'
);
Si vous exécutez ce code, vous aurez un beau message "Salut Antoine". En effet, la fonction replace() remplace l'occurrence de la regex par la valeur indiquée. Ici, elle remplace le "Michel" par un "Antoine"
Maintenant, si vous faites :
var
message =
'
Salut
Michel
!
Comment
vas-tu,
Michel
?
'
;
alert
(
message.
replace
(
/
Michel/
,
'
Antoine
'
);
Vous aurez un message "Salut Antoine ! Comment vas-tu, Michel ?". En effet, nous n'avons pas dit à la regex "remplace TOUTES les occurrences de Michel par Antoine". Il faut ajouter à la regex un petit caractère nommé flag (drapeau, en français), pour lui dire de faire le remplacement pour TOUTES les occurrences.
Le flag résolvant notre problème est le flag g. Les flags doivent être inscrits après la slash (/) fermant, comme ceci :
var
message =
'
Salut
Michel
!
Comment
vas-tu,
Michel
?
'
;
alert
(
message.
replace
(
/
Michel/
g,
'
Antoine
'
);
Et ça fonctionne !
Un autre flag est le flag i. Il permet d'indiquer à la regex d'être insensible à la casse, comme ceci :
var
message =
'
salut
MICHEL
'
;
if
(
message.
match
(
/
michel/
)) {
}
//
ne
fonctionne
pas
if
(
message.
match
(
/
michel/
i)) {
}
//
fonctionne
!
Cela peut également vous permettre de ne pas avoir à écrire de [a-z] dans votre regex :-) !
Le dernier flag que je vous montrerais dans ce cours est m. Il permet de dire "teste-moi ça sur chaque ligne" :
var
message =
'
Salut
Michel
!\nSalut
Jean
!\nSalut
Henri
!
'
;
if
(
message.
match
(
/
^
Salut Jean/
)) {
}
//
ne
fonctionne
pas,
car
la
chaîne
ne
commence
pas
par
"Salut
Jean"
if
(
message.
match
(
/
^
Salut Jean/
m)) {
}
//
fonctionne,
car
une
des
lignes
commence
par
"Salut
Jean"
Pratique, hein ?
Evidemment, utiliser des flags réduira la vitesse d'exécution de la regex, mais cela ne se ressentira pas pour un humain (exécuter une regex comme celle-ci prends moins d'un millième de seconde pour votre ordinateur !).
III.2. Remplacement avec données de regex▲
On va maintenant voir comment extraire des données d'une chaîne. Par exemple, vous avez une phrase. Celle-ci contient un code à 4 chiffres, que vous aimeriez bien connaître. On peut d'ores et déjà vérifier que le code est bien présent comme ceci :
/
(
[
0
-
9
]
){
4
}
/
Mais comment le récupérer ? On va en fait utiliser un petit symbole : $. Lorsqu'il est suivi d'un chiffre, il permet de récupérer une donnée. Par exemple, dans la regex :
/
(
Salut|
Bonjour|
Hey) (
Henri|
Martin)/
$1 vaudra soit "Salut", soit "Bonjour", soit "Hey".
$2 vaudra soit "Henri", soit "Martin"
Dans "Salut Martin", avec cette regex, $1 vaudra "Salut" et $2 vaudra "Martin" ! Pour récupérer ces valeurs, il faut utiliser la fonction match(), comme ceci :
var
message =
'
Tiens,
salut
Martin
!
'
;
var
match =
message.
match
(
/
(
salut|
bonjour) (
Henri|
Martin)/
);
Si vous regardez de plus près le contenu de match, vous pouvez voir que c'est un tableau, contenant :
- match[0] : toute l'occurrence (ici, "salut Martin") ;
- match[1] : vaut $1 (ici, "salut") ;
- match[2] : vaut $2 (ici, "Martin").
S'il y avait eu un $3, il aurait été stocké dans match[3], et ainsi de suite !
III.3. Remplacement par fonction▲
Sachez qu'on peut également passer autre chose qu'une chaîne de caractères comme second paramètre à la fonction replace, on peut aussi passer une fonction ! Ça s'écrit comme ça :
var
message =
'
salut
henri
'
;
alert
(
message.
replace
(
/
salut/
g,
function
(
) {
return
'
bonjour
'
;
Ce code aura pour effet de remplacer tous les "salut" par des "bonjour" !
Et on peut faire encore mieux !
var
message =
'
hey
martin
'
;
alert
(
message.
replace
(
/
(
salut|
hey)/
g,
function
(
) {
return
'
bonjour
'
;
Là, ça remplacera tous les "salut" et "hey" par des "bonjour" ! Et pour récupérer les données $1, $2 etc., on fait :
var
message =
'
tiens,
salut
martin
!
'
;
message.
replace
(
/
(
salut|
hey) (
henri|
martin)/
g,
function
(
match,
$1
,
$2
) {
console.
log
(
match,
$1
,
$2
);
}
);
Et que s'affiche-t-il dans la console ? Un tableau :-O ! En premier, le match, soit 'salut martin', ensuite $1, soit 'salut' et $2 'martin' ! On peut par exemple faire ceci :
var
message =
'
tiens,
salut
martin
!
'
;
alert
(
message.
replace
(
/
(
salut|
hey) (
henri|
martin)/
g,
function
(
match,
$1
,
$2
) {
return
'
bonjour
mon
bon
'
+
$2
;
}
));
Ce qui donnera 'tiens, bonjour mon bon martin !' (pas très original, mais bon) !
IV. T.P. final▲
1) Sujet
Vous allez devoir créer une regex capable de censurer les mots "le code est " suivi d'un code composé de chiffres et "le mot de passe est " suivi d'un mot composé de lettres. Je vous laisse choisir entre utiliser une fonction ou non pour le remplacement.
Prêt ? Allez-y !
2) Corrigé
On commence par créer la regex ? On doit remplacer toutes les occurrences de "le code est xxxx" et "le mot de passe est xxxx". Donc pour simplifier, on va faire deux regex !
/
le code est (
[
0
-
9
]
+
)/
i
/
le mot de passe est (
[
a-
z]
+
)/
i
Je rajoute un flag i pour ne pas que "le CODE est 1234" échappe à la regex. ;-)
Maintenant, on va effectuer le remplacement : on doit supprimer toutes ces occurrences, soit :
var
message =
'
salut,
le
code
est
4568
!\nhey,
le
mot
de
passe
est
maSLF
!
'
;
message =
message.
replace
(
/
le code est (
[
0
-
9
]
+
)/
i,
'
'
);
message =
message.
replace
(
/
le mot de passe est (
[
a-
z]
+
)/
i,
'
'
);
alert
(
message);
Et voilà le travail ! Maintenant, vous maîtrisez les regex JavaScript (PCRE) sur le bout des doigts0 ;-)
V. Remerciements▲
...