Plusieurs caractères ou classes de caractères, entourés de crochets [â¦] signifient âchercher un caractère parmi ceux-là â.
Ensembles
Par exemple, [eao] signifie un caractère qui est soit 'a', 'e', ou 'o'.
On appelle cela un ensemble. Les ensembles peuvent être combinés avec dâautres caractères dans une même expression régulière :
// trouve [t ou m], puis "op"
alert( "Mop top".match(/[tm]op/gi) ); // "Mop", "top"
Bien quâil y ait plusieurs caractères dans un ensemble, vous remarquez que lâon ne cherche la correspondance que dâun seul de ces caractères.
Lâexemple suivant ne donne donc aucun résultat :
// trouve "V", puis [o ou i], puis "la"
alert( "Voila".match(/V[oi]la/) ); // null, pas de correspondance
Lâexpression régulière recherche :
V,- puis une des lettres
[oi], - enfin
la.
Ce qui correspondrait à Vola ou Vila.
Intervalles
Les crochets peuvent aussi contenir des intervalles de caractères.
Par exemple, [a-z] est un caractère pouvant aller de a à z, et [0-5] est un chiffre allant de 0 à 5.
Dans lâexemple ci-dessous nous recherchons un "x" suivi par deux chiffres ou lettres de A Ã F:
alert( "Exception 0xAF".match(/x[0-9A-F][0-9A-F]/g) ); // xAF
Ici [0-9A-F] comporte deux intervalles : il recherche un caractère qui est soit chiffre entre 0 et 9 compris ou bien une lettre entre A et F comprise.
Si nous voulons y inclure les lettres minuscules, nous pouvons ajouter lâintervalle a-f: [0-9A-Fa-f]. Ou bien ajouter le marqueur i.
Nous pouvons aussi utiliser les classes de caractères entre [â¦].
Par exemple, si nous voulons chercher un caractère alphanumérique, un trait de soulignement \w ou un tiret -, alors lâensemble sâécrit [\w-].
Il est aussi possible de combiner plusieurs classes, p. ex. [\s\d] signifie âun caractère dâespacement ou un chiffreâ.
Par exemple:
- \d â équivaut Ã
[0-9], - \w â équivaut Ã
[a-zA-Z0-9_], - \s â équivaut Ã
[\t\n\v\f\r ], plus quelques autres rares caractères unicodes dâespacement.
Exemple : \w multi-langue
Comme la classe de caractères \w est un raccourci pour [a-zA-Z0-9_], il ne peut pas trouver les idéogrammes chinois, ni les lettres cyrilliques, etc.
Nous pouvons écrire un motif plus universel, pour rechercher le caractère dâun mot quelle que soit la langue. Grâce aux propriétés Unicode, on obtient facilement : [\p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C}].
Déchiffrons cela. Tout comme \w, nous construisons notre propre ensemble qui contient les caractères qui portent les propriétés Unicode :
Alphabetic(Alpha) â pour les lettres,Mark(M) â pour les accents,Decimal_Number(Nd) â pour les nombres,Connector_Punctuation(Pc) â pour le trait de soulignement'_'et autres caractères similaires,Join_Control(Join_C) â deux codes spéciaux200cet200d, utilisés comme liaisons, p. ex. en arabe.
Exemple dâusage :
let regexp = /[\p{Alpha}\p{M}\p{Nd}\p{Pc}\p{Join_C}]/gu;
let str = `Hi ä½ å¥½ 12`;
// trouve toutes les lettres et chiffres:
alert( str.match(regexp) ); // H,i,ä½ ,好,1,2
Cet ensemble est bien sûr encore modifiable : on peut y ajouter ou retirer des propriétés Unicode. Plus de détail sur ces propriétés Unicode dans lâarticle Unicode: indicateur "u" et classe \p{...}.
Les propriétés Unicode p{â¦} ne sont pas implémentées dans IE. Si nous en avons vraiment besoin, nous pouvons utiliser la librairie XRegExp.
Ou simplement utiliser des intervalles de caractères dans la langue qui nous intéresse, p. ex. [а-Ñ] pour les lettres cyrilliques.
Intervalles dâexclusion
En plus des intervalles classiques, il existe des intervalles dâexclusion de la forme [^â¦].
Ils se distinguent par un premier accent circonflexe ^ et correspond à nâimporte quel caractère à lâexception de ceux contenus dans ces crochets.
Par exemple :
[^aeyo]â nâimporte quel caractère sauf'a','e','y'ou'o'.[^0-9]â nâimporte quel caractère à lâexception des chiffres, équivalent Ã\D.[^\s]â tout caractère qui nâest pas un espacement, équivalent Ã\S.
Lâexemple ci-dessous cherche nâimporte quel caractère nâétant pas une lettre, un chiffre ou un espace :
alert( "alice15@gmail.com".match(/[^\d\sA-Z]/gi) ); // @ et .
Lâéchappement entre [â¦]
Habituellement, lorsque nous cherchons précisément un caractère spécial, nous devons lâéchapper \.. Et si nous cherchons un backslash, nous utilisons \\, etc.
à lâintérieur de crochets nous pouvons utiliser une grande majorité des caractères spéciaux sans échappement :
- Les symbols
. + ( )ne sont jamais échappés. - Un tiret
-nâest pas échappé en début ou fin dâensemble (là où il ne peut pas définir dâintervalle). - Un accent circonflexe
^est échappé uniquement sâil débute lâensemble (sinon il signifie lâexclusion). - Le crochet fermant
]est toujours échappé (si nous le cherchons précisément).
En dâautres termes, tous les caractères spéciaux ne sont pas échappés, sauf sâils ont un sens particulier pour un ensemble.
Un point . à lâintérieur de crochets signifie juste un point. Le motif [.,] recherche un caractère : soit un point soit une virgule.
Dans lâexemple ci-dessous lâexpression régulière [-().^+] cherche un des caractères -().^+:
// Pas besoin d'échapper
let regexp = /[-().^+]/g;
alert( "1 + 2 - 3".match(regexp) ); // trouve +, -
⦠Si vous décidez de les échapper, âau cas oùâ, il nây aura de toute façon aucun dâimpact :
// Tout échappé
let regexp = /[\-\(\)\.\^\+]/g;
alert( "1 + 2 - 3".match(regexp) ); // fonctionne aussi: +, -
Intervalles et marqueur âuâ
Sâil y a une paire de seizets dâindirection(surrogate pair) dans lâensemble, le marqueur u est requis pour quâelle soit interprétée correctement.
Par exemple, cherchons [ð³ð´] dans la chaîne ð³:
alert( 'ð³'.match(/[ð³ð´]/) ); // affiche un caractère étrange qui ressemble à [?]
// (la recherche n'a pas fonctionné correctement, seule une moitié du caractère est retournée)
Le résultat nâest pas celui attendu, car par défaut une expression régulière ne reconnait pas une telle paire.
Le moteur dâexpression régulière pense que [ð³ð´] â ne sont pas deux mais quatre caractères :
- la moitié gauche de
ð³(1), - la moitié droite de
ð³(2), - la moitié gauche de
ð´(3), - la moitié droite de
ð´(4).
On peut voir le code de ces caractères ainsi :
for(let i=0; i<'ð³ð´'.length; i++) {
alert('ð³ð´'.charCodeAt(i)); // 55349, 56499, 55349, 56500
};
Donc, le premier exemple trouve et affiche la première moitié de ð³.
Mais si nous ajoutons le marqueur u, on aura alors le comportement attendu :
alert( 'ð³'.match(/[ð³ð´]/u) ); // ð³
On retrouve un mécanisme similaire dans les intervalles, comme [ð³-ð´].
Si nous oublions le marqueur u, il y aura une erreur :
'ð³'.match(/[ð³-ð´]/); // Error: Invalid regular expression
En effet sans le marqueur u une paire de seizets est perçue comme deux caractères distincts, donc [ð³-ð´] est interprété en [<55349><56499>-<55349><56500>] (chacune des paires est remplacée par ses codes). Il est maintenant évident que lâintervalle 56499-55349 nâest pas valide : le premier code 56499 est plus grand que le dernier 55349. Ce qui explique lâerreur précédente.
Avec le marqueur u le motif est interprété correctement :
// Cherche un caractère entre ð³ et ðµ compris
alert( 'ð´'.match(/[ð³-ðµ]/u) ); // ð´
Commentaires
<code>, pour plusieurs lignes â enveloppez-les avec la balise<pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepenâ¦)