Les parenthèses permettent de chercher un critère complexe ou d'isoler des alternatives.
La construction d'une expression régulière dépend uniquement de la connaissance des opérateurs d'expression régulière et caractères spéciaux, ainsi que des modifieurs globaux.
Les opérateurs, intervalles et groupes Les opérateurs, intervalles et groupes En regroupant des éléments dans une expression, on peut appliquer des opérateurs logiques. Ajoutant à cela les intervalles, il devient possible d'exprimer en peut de lettres un ensemble de règles.
Le point Le point désigne tout caractère dans le texte à comparer. Sauf le code de fin de ligne.
Groupes ()
Les parenthèses désignent un groupe de rappel, trouve l'élément entre parenthèse et le mémorise pour le restituer dans le tableau résultat ou dans les variables de l'objet RegExp. Le masque (.) désigne un caractère quelconque. Associé à l'opérateur +, donc (.)+ cela signifie un caractère quelconque au moins, donc un seul caractère ou une chaîne de caractères.
Par exemple (ari) permet de retrouver "ariane", ou "baril", et mais "carquois" n'est pas retenu. Puis ari est mémorisé.
(?:x)
Parenthèses non capturantes. On recherche l'élément x, mais il n'est pas mémorisé et n'apparaît pas dans le résultat pour la méthode qui retourne un tableau. Ni dans les variables internes.
[]
Les crochets désignent un groupe alternatif. On recherche l'un ou l'autre des éléments dans la liste. Dans le cas ou l'on recherche [abc], alors "ariane", "baril", "corail" peuvent correspondre (si l'on teste la première lettre).
Intervalle -
Le symbole tiret désigne entre deux lettres ou chiffres désigne un intervale. Exemples: a-z liste des lettres minuscules. N'importe quelle lettre dans la liste peut correspondre. A-Z liste des majuscules. 0-9 liste des chiffres.
Opérateurs de parties Ces symboles servent à désigner une partie spéficifique des textes à comparer avec l'expression régulière.
^
Spécifie que l'élément qui suit, caractère ou groupe, doit être placé au début du texte pour qu'il corresponde à la recherche. Si le masque est /^e/ le texte "enfin" est retenu et pas "terme". Dans le cas d'un texte en plusieurs lignes, avec le modifieur "m" en option, cela s'applique au début de chaque ligne.
$
Spécifie que l'élément précédent, caractère ou groupe doit terminer la fin du texte. Si le masque est /e$/ le texte "enfin" n'est pas retenu, mais "ariane" le serait . Dans le cas d'un texte en plusieurs lignes, avec le modifieur "m" en option, cela s'applique à la fin de chaque ligne.
?
L'élément précédant peut être présent ou non. a? signifie qu'il peut y avoir une lettre a ou aucune. Cela permet de passer le caractère lorsqu'il est présent pour appliquer la suite de l'expression régulière sur la partie du texte qui vient après.
Opérateurs de quantité +
Il doit y avoir ou moins un élément de la lettre ou du groupe précédant le symbole.
Exemples: a+ il doit y avoir un a ou plusieurs. [abc]+ il doit y avoir un a ou un b ou un c ou plusieurs de ces mêmes lettres (pas une combinaison).
*
Il peut y avoir un nombre indéterminé d'occurence du texte précédent, ou aucune.
{ n }
n représente un nombre entier quelconque. C'est le nombre d'occurences que l'on recherche. Exemple: a{2} On recherche une chaîne qui contient "aa".
{ x, y }
x et y représentent deux nombres entiers positifs. Il y aura au moins x occurences et au plus y occurences. Par exemple { 2, 3 } On recherche deux ou trois occurences d'une chaîne.
Opérateurs logiques x | y
La barre est l'opérateur OU inclusif. Exemple: (abc | def) On recherche la chaîne qui contient abc ou def (ou les deux).
[^]
Le symbole "^" quand il est entre crochets ne désigne pas le début d'un ensemble mais l'exclusion de cet ensemble. Exemple: [^xyz] L'expression représente toutes les lettres sauf x, y ou z.
Opérateurs conditionnels x(?=y)
Le texte correspond quand x est suivi par y. Exemple: moi(?=elle) Quand moi est suivi directement par elle dans le texte, l'expression est satisfaite. Pour conserver les deux chaînes dans le tableau résultat, on écrira: moi(?=(elle))
Exemple: (0-9)+(?=\.)(0-9)+ Représente un nombre décimal: suite de chiffres, point, et décimales. Cela peut s'écrire plus simplement: \d+\.\d+
x(?!y)
Le texte x correspond s'il n'est pas suivi par y. Pour représenter un nombre entier on écrirait: [0-9]+(?!\.) mais [0-9]+ serait plus simple.
Note importante
Dans une chaîne de caractères, le code "\" doit être doublé. Par exemple on écrira \\d pour représenter le symbole \d , un digit. Ce n'est pas le cas quand on entre l'expression régulière dans un formulaire, ni dans la forme litérale:
/\d+/
(?<=y)x
Correspond à x seulement si x est précédé par y. C'est ce qu'on appelle une recherche arrière (lookbehind). Ainsi /(?<=Jack)Sprat/ correspond à "Sprat" seulement s'il est précédé de "Jack". /(?<=Jack|Tom)Sprat/ correspond à "Sprat" seulement s'il est précédé de "Jack" ou "Tom". Toutefois, "Jack" et "Tom" ne feront pas partie de la correspondance.
(?<!y)x
Correspond à x uniquement si x n'est pas précédé par y (parfois appelée en anglais negated lookbehind). Ainsi, (?<!non\W?)miscibles?
Dans la phrase : « Ces deux liquides sont miscible.» la correspondance sera trouvée car le mot miscible n'est pas précédé du mot "non" Dans les phrases : « Ces deux liquides sont nonmiscible. » « Ces deux liquides sont non-miscible. » « Ces deux liquides sont non miscible. » ne trouve aucune correspondance car le mot "miscible" est précédé du mot "non" qu'il soit attaché ou non au mot "miscible". Les quantificateurs gourmands et fainéants Les quantificateurs gourmands et fainéants Que sont les quantificateurs ? Commençons par un peu de grammaire et de vocabulaire, de quoi parlons-nous ? Et comment cela s’articule-t-il ?
Les quantificateurs permettent de préciser dans une regex le nombre d’occurrences attendues pour un caractère ou un groupe de caractères donné. Pour cela, des caractères ayant une signification spécifique sont mis à notre disposition. Il s’agit du point d’interrogation ?
, de l’étoile *
, du signe plus +
, ainsi que des accolades {}
.
Voici leur signification :
a?
zéro ou une occurrence de a
a*
zéro ou plusieurs occurrences de a
a+
une ou plusieurs occurrences de a
a{3}
exactement trois occurrences de a
a{3,}
trois occurrences de a
ou davantagea{3,6}
trois à six occurrences de a
Le gourmand Par défaut, les quantificateurs sont gourmands (ou greedy en anglais), c’est-à-dire qu’ils maximisent la concordance. Dit autrement, tant qu’un caractère correspond au motif recherché, il sera consommé. Prenons un exemple.
Supposons que nous faisons une recherche dans la chaîne andouillette AAAAA
à l’aide de cette regex :
/ ( .* ) A /
Voici ce qui en résulterait :
Concordance complète (0-18) : andouillette AAAAA Groupe 1 (0-17) : andouillette AAAA
Expliquons-nous. Nous recherchons n’importe quel caractère, un nombre indéterminé de fois .*
, c’est là notre groupe 1 ; suivi pour finir du caractère A
. Notre quantificateur étant gourmand, il va consommer tous les caractères de la chaîne, sauf le dernier A
de façon à ce qu’il puisse y avoir concordance.
Le fainéant Il est possible d’obtenir le comportement inverse. C’est-à-dire minimiser la concordance. Pour cela, il nous faut suffixer notre quantificateur d’un point d’interrogation *?
. On parle alors de quantificateur fainéant ou lazy .
Prenons le même exemple, mais en le comparant cette fois à cette regex :
/ ( .* ? ) A /
Concordance complète (0-14) : andouillette A Groupe 1 (0-13) : andouillette
À présent, sitôt qu’un sous-ensemble de notre chaîne de caractère fait l’affaire, la concordance s’arrête. Notre quantificateur nous empêche d’en parcourir davantage.
Cet exemple peut s’avérer très artificiel. Voyons un cas plus concret. Disons que vous souhaitez récupérer l’ensemble des attributs d’une balise HTML. Par exemple, celle-ci :
<a href= "https://www.synbioz.com" > Synbioz</a>
Votre première idée serait peut-être d’écrire un regex comme celle-ci :
/ <a ( .* ) > .* < / a>` /
Concordance complète (0-45) : <a href="https://www.synbioz.com">Synbioz</a> Groupe 1 (3-33) : href="https://www.synbioz.com"
Effectivement, cela fonctionne et le premier groupe contiendra bien la sous-chaîne recherchée href="https://www.synbioz.com"
. Mais on peut obtenir une regex plus concise grâce à un quantificateur fainéant :
/ <a ( .* ? ) > /
Concordance complète (0-34) : <a href="https://www.synbioz.com"> Groupe 1 (3-33) : href="https://www.synbioz.com"
Notons que dans ce cas très précis, l’approche la plus efficace, mais dont l’intention est bien moins déchiffrable, reste l’utilisation d’une classe de caractères négative telle [^>]
, c’est-à-dire « tout sauf un chevron >
» — comme ceci :
/ <a ([^ > ] * ) > /
Concordance complète (0-34) : <a href="https://www.synbioz.com"> Groupe 1 (3-33) : href="https://www.synbioz.com"
Il y a toujours plusieurs moyens d’arriver à ses fins à l’aide d’une regex, le tout étant de savoir quelle est votre priorité : la performance ou la compréhensibilité.
Le possessif Le dernier modificateur dont nous disposons est le possessif (ou possessive en anglais). Le possessif, qui se note *+
, est gourmand et empêche tout retour en arrière. Autrement dit, tout caractère consommé ne pourra être relâché pour tenter de trouver une concordance.
Si l’on reprend notre « andouillette AAAAA » comme exemple avec notre nouvelle regex…
/ ( .* + ) A /
…nous n’aurions alors aucune concordance ! Pour bien saisir, il faut comprendre le fonctionnement interne d’une recherche de concordance. Le moteur de regex commencera au début de notre chaîne, consommera tous les caractères .*+
puis recherchera un A
. Mais il n’y en a plus, car tout a été consommé et notre quantificateur ne restitue aucun caractère consommé pour aider le moteur de regex à trouver une concordance. Qu’à cela ne tienne, notre petit moteur va commencer sa recherche à partir du deuxième caractère… ce qui aura la même issue malheureuse. Il tentera donc à partir du troisième, et ainsi de suite, nous menant toujours dans une impasse, dans l’impossibilité de donner satisfaction à cette regex.
Alors, à quoi cela sert-il, me direz-vous !? L’intérêt d’un quantificateur possessif réside essentiellement dans la performance : il permet d’échouer plus vite en empêchant le moteur de regex d’effectuer certaines permutations.
Les caractères spéciaux Les caractères spéciaux Les caractères spéciaux sont introduits par le code d'échappement "\". Dans un littéral (ou un formulaire) mais dans une chaîne, le slash inversé est doublé.
x = /a\r/
x = new RegExp ("a\\r" )
Celui-ci associé à une lettre représente un code qui ne peut être affiché directement, mais il sert aussi, quand il est associé à un code opérateur, à désigner le caractère plutôt que l'opérateur d'expression régulière:
\n désigne la fin de ligne et non pas la lettre n.
\* désigne le caractère étoile et non pas l'opérateur d' expression régulière étoile.
\t code de tabulation. \v pour une tabulation verticale.
\r code de retour à la ligne.
\f code de fin de page.
\s code de s éparation quelconque , incluant :espace blanc , tabulation , retour à la ligne , fin de page .
\S tout caractère autre qu'un espace, c' est le contraire de \s.
\d tout digit , autrement dit tout caract ère num érique . Equivaud à [0-9] .
\D tout caract ère non num érique . Equivaud à [^0-9] .
\w tout caract ère alphanum érique . Equivaud à [_A-Za-z0-9] .
\W tout caractère autre qu'alphanumérique. C' est le contraire de \w et cela équivaud à [^_A-Za-z0-9 ].
\nnnn où nnnn est un nombre entier positif.
\0 Représente le code 0 dans le fichier binaire (et non le chiffre 0 dans le texte).
\xhh Où hh est un couple hexadécimal. Représente un code dans le binaire.
\uhhhh Code hexadécimal sur 4 digits.