Visit Mozilla.org

Guide JavaScript 1.5:Expressions rationnelles

Un article de MDC.


Sommaire

[modifier] Création d'une expression rationnelle

Vous pouvez construire une expression rationnelle de deux façons :

  • En utilisant une expression rationnelle directe d'une façon littérale, comme ci-dessous :
 re = /ab+c/;
Les expressions rationnelles directes permettent la compilation de l'expression rationnelle lors de la lecture du script. Si cette dernière est censée rester constante, mieux vaut utiliser cette méthode pour de meilleures performances.
  • En appelant le constructeur d'objets RegExp, comme ceci :
 re = new RegExp("ab+c");
L'utilisation du constructeur d'objets permet la compilation de l'expression rationnelle à l'exécution. Utilisez le constructeur d'objets si vous savez que l'expression rationnelle est amenée à changer, ou si vous ne connaissez pas le masque et l'obtenez d'une autre source, par une entrée clavier par exemple.


[modifier] Écriture d'un masque d'expression rationnelle

Un masque d'expression rationnelle est composé de caractères simples, comme par exemple /abc/, ou d'une combinaison de caractères simples et de caractères spéciaux, comme /ab*c/ ou /Chapitre (\d+)\.\d*/. Le dernier exemple comporte des parenthèses, qui sont utilisées comme des « cases mémoires ». La capture de cette partie du modèle est conservée pour un usage ultérieur, comme décrit dans Utilisation des parenthèses de capture.

[modifier] Utilisation de masques simples

Les masques simples sont des assemblages de caractères pour lesquels une correspondance exacte est souhaitée. Par exemple, le modèle /mou/ correspond à des combinaisons de caractères dans des chaînes seulement quand les caractères « mou » apparaissent ensemble et dans cet ordre. Une telle correspondance est présente dans les chaines « Ce coussin est mou » et « Il faut promouvoir ce produit. » Dans les deux cas il y a capture de la sous-chaîne « mou ». Il n'y a pas de capture dans la chaîne « Loukoum oublié » car elle ne contient pas la sous-chaîne « mou ».

[modifier] Utilisation de caractères spéciaux

Quand la recherche nécessite quelque chose de plus avancé qu'une correspondance exacte, comme trouver un ou plusieurs « b », ou trouver des espaces, le masque contient des caractères spéciaux. Par exemple, le masque /ab*c/ correspond à toute combinaison de caractères dans laquelle un seul « a » est suivi de zéro ou plus « b » (l'astérisque * signifie 0 ou plus occurences de l'objet précédent) immédiatement suivis d'un « c ». Dans le chaîne « cbbabbbbcdebc », le masque capture la sous-chaîne « abbbbc ».

Le tableau suivant fournit une liste complète des caractères spéciaux pouvant être utilisés dans des expressions rationnelles, ainsi que leur rôle.

Caractère Signification
\ Deux significations sont possibles :
  • Pour les caractères qui sont habituellement traités littéralement, indique que le prochain caractère est spécial et n'a pas à être interprété littéralement. Par exemple, /b/ correspond au caractère « b ». En plaçant un antislash devant b, ce qui donne /\b/ , le caractère devient un séparateur de mots.
  • Pour les caractères qui sont habituellement traités comme des caractères spéciaux, il indique que le prochain caractère n'est pas un caractère spécial et doit être interprété littéralement. Par exemple, * est un caractère spécial qui signifie que 0 ou plus d'occurences de l'objet précédent doivent apparaître ; par exemple, /a*/ signifie que 0 ou plus de « a ». Pour capturer le caractère * littéralement, faites-le précéder d'un antislash ; par exemple, /a\*/ capture « a* ».
^ Capture le début d'une chaîne. Si l'indicateur « multiligne » est activé, capture aussi la début d'une ligne, c.-à-d. juste après un caractère de retour chariot. Par exemple, /^U/ ne ne capture pas « U » dans "un U", mais capture le premier « U » dans "Un U".
$ Capture la fin d'une chaîne. Si l'indicateur « multiligne » est activé, capture aussi la fin d'une ligne, c.-à-d. juste avant un caractère de fin de ligne. Par exemple, /k$/ ne capture pas « k » dans "cracker", mais le capture dans "crack".
* Capture le caractère précédent répété 0 fois ou plus. Par exemple, /beu*/ capture « beuuuuuuuuuu » dans "Ces épinards sont beuuuuuuuuuurk" et « be » dans "Un belge", mais ne capture rien dans "Une blatte".
+ Capture le caractère précédent répété 1 ou plusieurs fois. Equivalent à {1,}. Par exemple, /a+/ capture la « a » dans "candide" et tous les « a » dans "caaaaaaandide".
? Capture le caractère précédent apparaissant 0 ou 1 fois.

Par exemple, /e?le?/ capture le « el » dans "carrousel" et le « le » dans "angle".

S'il est utilisé après un quantificateur *, +, ?, ou {}, il le rend « non-vorace » (capture un minimum de fois), contrairement à la configuration par défaut, qui est « vorace » (capture un maximum de fois). Il est utilisé également dans les assertions rétroactives, décrites par x(?=y) et x(?!y) dans ce tableau.

. Le point capture tout caractère unique, excepté le retour chariot. Par exemple, /.n/ capture « an » et « on » dans "nay, an apple is on the tree", mais pas « nay ».
(x) Capture « x » et retient l'instance. Elles sont appelées « parenthèses capturantes ». Par exemple, /(foo)/ capture et instancie « foo » dans "foo bar". La sous-chaîne capturée peut être récupérée dans un tableau de résultats : [1], ..., [n].
(?:x) Capture « x » sans instance. Ce sont des parenthèses non-capturantes. La sous-chaîne capturée ne peut donc pas être récupérée.
x(?=y) Capture « x » seulement si « x » est suivi de « y ». Par exemple, /Jack(?=Sprat)/ capture « Jack » seulement si il est suivi de « Sprat ». /Jack(?=Sprat|Frost)/ capture « Jack » seulement si il est suivi de « Sprat » ou de « Frost ». Cependant, ni « Sprat » ni « Frost » ne sont capturés.
x(?!y) Capture « x » seulement si « x » n'est pas suivi de « y ». Par exemple, /\d+(?!\.)/ capture un nombre seulement s'il n'est pas suivi d'un point. L'expression rationnelle /\d+(?!\.)/.exec("3.141") capture 141 mais pas 3.141.
x|y Capture soit « x » soit « y ». Par exemple, /verte|rouge/ capture « verte » dans "pomme verte" et « rouge » dans "pomme rouge"
{n} Avec n entier positif, capture n occurences du caractère précédent. Par exemple, /a{2}/ ne capture pas la « a » de "candy", mais capture tous les « a » de "caandy" et les deux premiers dans "caaandy".
{n,} Avec n entier positif, capture au moins n occurences du caractère précédent. Par exemple, /a{2,}/ ne capture pas le « a » de "candy", mais capture tous les « a » de "caandy" et de "caaaaaaandy".
{n,m} Avec n et m deux entiers positifs, capture au moins n occurences et au plus m occurences du caractère précédent. Par exemple, /a{1,3}/ ne capture rien dans "cndy", le « a » de "candy", les deux premiers « a » de "caandy", et les trois premiers « a » de "caaaaaaandy". Remarquez que lors de la capture de "caaaaaaandy", seul "aaa" est capturé, même si la chaîne possède plus de « a ».
[xyz] Jeu de caractères. Capture n'importe quel caractère contenu entre les crochets. Vous pouvez spécifier une gamme de caractères en utilisant un trait d'union. Par exemple, [abcd] est identique à [a-d]. Ils capturent le « b » de "basket" et le « c » de "hache".
[^xyz] Anti-jeu de caractères. Il capture tous les caractères qui n'appartiennent pas à la liste des caractères présents entre les crochets. Vous pouvez spécifier une gamme de caractères en utilisant un trait d'union. Par exemple, [^abc] est identique à [^a-c]. Ils capturent 'a' dans "basket" et « h » dans "chope".
[\b] Capture une suppression arrière (à ne pas confondre avec \b.)
\b Capture un séparateur de mots, tel qu'un espace ou un retour chariot.(A ne pas cofondre avec [\b].) Par exemple, /\bn\w/ capture le « no » de "noonday" ; /\wy\b/ capture le « ly » de "possibly yesterday".
\B Capture un non-séparateur de mots. Par exemple, /\w\Bn/ capture « on » dans "noonday", et /y\B\w/ capture « ye » dans "possibly yesterday".
\cX X étant un caractère de contrôle, capture un caractère de contrôle dans une chaîne. Par exemple, /\cM/ capture Ctrl-M dans une chaîne.
\d Capture un chiffre. equivalent à [0-9]. Par exemple, /\d/ ou /[0-9]/ capture « 2 » dans "B2 est le numéro de la chambre".
\D capture un caractère non-numérique. Equivalent à [^0-9]. Par exemple, /\D/ ou /[^0-9]/ capturent « B » dans "B2 est le numéro de la chambre".
\f Capture une fin de formulaire.
\n Capture une fin de ligne.
\r Capture un retour chariot.
\s Capture un blanc : soit une simple espace, soit une tabulation, soit une fin de ligne, soit une fin de formulaire. Equivalent à [ \f\n\r\t\v\u00A0\u2028\u2029]. Par exemple, /\s\w*/ capture «  bar » dans "foo bar".
\S Capture un caractère qui n'est pas un blanc. Equivalent à

[^ \f\n\r\t\v\u00A0\u2028\u2029].

Par exemple, /\S\w*/ capture « foo » dans "foo bar".
\t Capture une tabulation.
\v Capture une tabulation verticale.
\w Capture un caractère alphanumérique, y compris les soulignés. Equivalent à [A-Za-z0-9_]. Par exemple, /\w/ capture « p » dans "pomme", « 5 » dans "$5.28" et « 3 » dans "3D".
\W Capture un caractère non-alphanumérique.Équivalent à [^A-Za-z0-9_]. Par exemple, /\W/ ou /[^$A-Za-z0-9_]/ capturent « % » dans "50%".
\n Quand n est un entier positif, une référence arrière à la dernière sous-chaîne capturant la nième parenthèse de l'expression rationnelle (y compris les parenthèses gauches). Par exemple, /pomme(,)\sorange\1/ capture « pomme, orange, » dans "pomme, orange, cerise, pêche."
\0 Capture le caractère nul. Ne le faites pas suivre pas un autre chiffre.
\xhh Capture le caractère dont le code hexadécimal est hh. (Simple)
\uhhhh Capture le caractère dont le code hexadécimal est hhhh. (Double).

Table 4.1: Caractères spéciaux des expressions rationnelles.

[modifier] Utilisation des parenthèses

L'ajout de parenthèses autour d'une partie d'un masque d'expression rationnelle fait que la sous-chaîne capturée entre parenthèses est conservée en mémoire. Une fois conservée, la sous-chaîne peut être récupérée pour être réutilisée, comme décrit dans Utilisation des parenthèses de capture.

Par exemple, le masque /Chapitre (\d+)\.\d*/ illustre l'utilisation de caractères spéciaux et indique qu'une partie du masque doit être conservée en mémoire. Il capture exactement les caractères « Chapitre  » suivis d'un ou plusieurs chiffres (\d signifie chiffre et + signifie 1 ou plusieurs fois), suivis d'un point (qui est un caractère spécial, c'est pourquoi on le fait précéder d'un caractère d'échappement afin qu'il ne soit pas interprété comme un caractère spécial), suivi de chiffres absents ou présents une ou plusieurs fois (\d signifie chiffre, * signifie 0 ou plus de fois). De plus, les parenthèses sont utilisées afin de conserver la première partie numérique.

Ce masque capture "Ouvrez le Chapitre 4.3, paragraphe 6", et conserve le « 4 ». Il ne capture pas "Chapitre 3 et 4", car le « 3 » n'est pas suivi d'un point.

Pour capturer une sous-chaîne sans qu'elle soit conservée en mémoire, faites précéder le masque à l'intérieur des parenthèses de ?:. Par exemple,(?:\d+) capture un ou plusieurs chiffres mais ne les conserve pas en mémoire.




[modifier] Travailler avec les expressions rationnelles

Les expressions rationnelles sont utilisées avec les méthodes test et exec de RegExp, et avec les méthodes match, replace, search et split de String. Ces méthodes sont expliquées en détail dans la Référence de JavaScript 1.5 Core.

Méthode Description
exec Une méthode de RegExp qui effectue une recherche de correspondance dans une chaîne. Elle renvoie un tableau de valeurs.
test Une méthode de RegExp qui teste la correspondance d'une chaîne. Elle renvoie true ou false.
match Une méthode de String qui effectue une recherche de correspondance dans une chaîne. Elle renvoie un tableau de valeurs ou null en cas d'échec.
search Une méthode de RegExp qui teste la correspondance d'une chaîne. Elle renvoie l'index de la capture, ou -1 en cas d'échec.
replace Une méthode de String qui effectue une recherche de correspondance dans une chaîne, et remplace la sous-chaîne capturée par la chaîne de remplacement.
split Une méthode de String qui utilise une expression rationnelle ou une chaîne pour diviser une chaîne en un tableau de sous-chaînes.

Tableau 4.2 : Méthodes utilisant les expressions rationnelles

Quand vous voulez savoir si un masque a trouvé une correspondance dans une chaîne, utilisez les méthodes test ou search ; pour obtenir des informations supplémentaires (mais un temps d'exécution plus long), utilisez les méthodes exec ou match. Si vous utilisez exec ou match et si la capture est réussie, ces méthodes retourneront un tableau et mettront à jour les variables de l'objet RegExp associé. Si la capture échoue, la méthode exec renverra null (qui se convertit en false).

Dans cet exemple, le script utilise la méthode exec pour trouver une correspondance dans une chaîne.

<script type="text/javascript">
  monExpr = /d(b+)d/g;
  monTableau = monExpr.exec("cdbbdbsbz");
</script>

Si vous n'avez pas besoin d'accéder aux propriétés de l'expression rationnelle, il y a une autre façon de créer monTableau dans ce script :

<script type="text/javascript">
  monTableau = /d(b+)d/g.exec("cdbbdbsbz");
</script>

Si vous voulez construire une expression rationnelle à partir d'une chaîne de caractères, il existe encore une autre alternative :

<script type="text/javascript">
  monExpr = new RegExp ("d(b+)d", "g");
  monTableau = monExpr.exec("cdbbdbsbz");
</script>

Avec ces scripts, la capture réussit et renvoie un tableau, tout en mettant à jour les propriétés présentées dans le tableau ci-dessous.

Objet Propriété ou Index Description Dans cet exemple
monTableau   La chaîne capturée ainsi que les sous-chaînes conservées en mémoire. ["dbbd", "bb"]
  index L'index de la capture dans la chaîne (commence à 0). 1
  input La chaîne d'origine. "cdbbdbsbz"
  [0] La dernière capture. "dbbd"
monExpr lastIndex L'index de départ de la prochaine capture. (Cette variable n'est disponible que si l'expression rationnelle utilise l'option g, décrite dans Exécution de recherches globales, ignorer la casse, utilisation de chaînes multilignes) 5
  source Le masque d'origine. Mis à jour à la création de l'expression rationnelle, et non lors de son exécution. "d(b+)d"

Tableau 4.3 : Résultats de l'exécution d'une expression rationnelle.

Comme montré dans le second exemple, il est possible d'utiliser une expression rationnelle créée à l'aide du contructeur d'objets sans l'assigner à une variable. Cependant, dans ce cas, chaque occurence crée une nouvelle expression rationnelle ; si vous utilisez cette technique, vous ne pouvez pas accéder aux propriétés de cette expression rationnelle. Par exemple, examinez ce script :

<script type="text/javascript">
  monExpr = /d(b+)d/g;
  monTableau = monExpr.exec("cdbbdbsbz");
  document.writeln("La valeur de lastIndex est " + monExpr.lastIndex);
</script>

Ce script affiche:

La valeur de lastIndex est 5

Cependant, si l'on avait ce script :

<SCRIPT type="text/javascript">
  monTableau = /d(b+)d/g.exec("cdbbdbsbz");
  document.writeln("La valeur de lastIndex est " + /d(b+)d/g.lastIndex);
</SCRIPT>

On obtiendrait :

La valeur de lastIndex est 0

Les occurences de /d(b+)d/g dans les deux instructions sont deux expressions rationnelles différentes et elles possèdent des valeurs différentes pour leur propriété lastIndex. Si vous voulez accéder aux propriétés d'une expression rationnelle, vous devez donc d'abord l'assigner à une variable.


[modifier] Utilisation des parenthèses de capture

La partie d'une expression rationnelle située entre parenthèses sera capturée puis mise en mémoire. Par exemple, /a(b)c/ capture les caractères « abc » et conserve « b ». Pour récupérer les captures mises entre parenthèses, utilisez le tableau de valeurs de retour : Array [1], [2], ..., [n].

Le nombre de sous-chaînes capturées et conservées est illimité. Le tableau de retour renvoie toutes celles qui ont été trouvées. L'exemple suivant montre comment utiliser les parenthèses de capture.

Exemple 1.
Ce script utilise la méthode replace pour inverser les mots de la chaîne. Pour le texte de remplacement, on utilise $1 et $2 pour appeler les premières et secondes captures entre parenthèses.

<script type="text/javascript">
 re = /(\w+)\s(\w+)/;
 str = "Jean Dupont";
 newstr = str.replace(re, "$2, $1");
 document.write(newstr)
</script>

On obtient « Dupont, Jean ».

Exemple 2.
Note : dans la fonction getInfo, la méthode exec est appelée grâce à la notation (), qui fonctionne dans Firefox mais dans peu d'autres navigateurs.

<html>

<script type="text/javascript">
 function getInfo(champ){
   var a = /(\w+)\s(\d+)/(champ.value);
   window.alert(a[1] + ", votre âge est " + a[2]);
 }
</script>

Entrez votre prénom et votre âge, puis appuyez sur Entrée.

<form>
  <input type="text" name="NameAge" onchange="getInfo(this);">
</form>

</html>



[modifier] Exécution de recherches globales, ignorer la casse, utilisation de chaînes multilignes

Les expressions rationnelles possèdent trois options qui permettent des recherches globales et non sensibles à la casse. Pour indiquer une recherche globale, utilisez l'option g. Pour indiquer une recherche non sensible à la casse, utilisez l'option i. Pour indiquer une recherche multiligne, utilisez l'option m. Ces trois options peuvent être utilisées séparément ou ensemble, et dans n'importe quel ordre. Elles sont considérées comme partie intégrante de l'expression rationnelle.

Pour inclure une option dans votre expression rationnelle, utilisez cette syntaxe :

re = /pattern/flags
re = new RegExp("pattern", ["flags"])

Notez que les options font partie intégrante de l'expression rationnelle ; elles ne peuvent pas être ajoutées ou retirées après la déclaration.

Par exemple, re = /\w+\s/g crée une expression rationnelle recherchant un ou plusieurs caractères suivis d'un espace sur l'ensemble de la chaîne.

<script type="text/javascript">
 re = /\w+\s/g;
 str = "fee fi fo fum";
 myArray = str.match(re);
 document.write(myArray);
</script>

Ce script affiche ["fee ", "fi ", "fo "]. Dans cet exemple, vous pouvez remplacer la ligne :

re = /\w+\s/g;

par :

re = new RegExp("\\w+\\s", "g");

et obtenir le même résultat.

L'option m est utilisée pour spécifier qu'une chaîne possédant plusieurs lignes doit être traitée en tenant compte de ces lignes. Si l'option m est utilisée, ^ et $ capturent le début et la fin de chaque ligne au lieu de ne capturer que le début et la fin de la chaîne.




[modifier] Exemples

Les exemples suivants montrent comment utiliser une expression rationnelle.

[modifier] Modifier l'ordre dans une chaîne entrante

L'exemple ci-dessous illustre la formation d'expressions rationnelles et l'utilisation de string.split() et de string.replace(). Il reformate une chaîne contenant des noms (prénoms d'abord) séparés par des espaces et/ou des tabulations et exactement un point-virgule. Puis il inverse l'ordre des noms (nom de famille d'abord) et trie la liste.

<script type="text/javascript">

// La liste des noms contient des noms tous séparés par des points virgules
// mais peut contenir plusieurs espaces et tabulations
var names = "Jean Dupond ;Fred Dubois; Matthieu Dubuisson ; Jacques chailloux ; Marc Raquin ";

var output = new Array(
  "---------- Chaîne d'origine<br><br>",
  names + "<br><br>");

// Prépare deux expressions rationnelles ainsi que le tableau de valeurs.
// Divise la chaîne en un tableau.

// masque : espaces possibles + point-virgule + espaces possibles
var pattern = /\s*;\s*/;

// Divise les noms à l'aide du masque ci-dessous
// et récupère les morceaux dans un tableau appelé nameList
var nameList = names.split(pattern);

// second masque : un ou plusieurs caractères + espace + un ou plusieurs caractères
// utilise les parenthèses pour conserver les captures
// les parties capturées sont récupérées plus tard.
var pattern = /(\w+)\s+(\w+)/;

// nouveau tableau pour l'analyse des noms
var bySurnameList = new Array();

// Affiche le tableau des noms et le remplit
// avec des noms séparés par des virgules
//
// la méthode replace enlève toutes les captures
// et les remplace par une chaîne en mémoire
// ici, seconde capture puis virgule puis espace puis première capture
//
// Les variables $1 et $2 réfèrent aux captures 1 et 2
// trouvées lors de l'analyse du dernier masque

output.push("---------- Après séparation<br>");

var i, len;
for (i = 0, len = nameList.length; i < len; i++)
{
  output.push(nameList[i] + "<br>");
  bySurnameList[i] = nameList[i].replace(pattern, "$2, $1")
}

// Affiche le nouveau tableau.
output.push("---------- Noms inversés<br>");
for (i = 0, len = bySurnameList.length; i < len; i++)
{
  output.push(bySurnameList[i] + "<br>")
}

// Trie par nom de famille et affiche le résultat
bySurnameList.sort();
output.push("---------- Triés<br>");
for (i = 0, len = bySurnameList.length; i < len; i++)
{
  output.push(bySurnameList[i] + "<br>")
}

output.push("---------- Fin<br>");

document.write(output.join("\n"));

</script>

[modifier] Utilisation de caractères spéciaux pour vérifier une entrée

Dans cet exemple, l'utilisateur entre un numéro de téléphone. Quand il appuie sur Entrée, le script vérifie la validité du numéro. S'il est valide (s'il est capturé par l'expression rationnelle), le script affiche une fenêtre de confirmation. S'il n'est pas valide, le script affiche une fenêtre avertissant que le numéro n'est pas valide.

L'expression rationnelle recherche zéro ou une parenthèse d'ouverture \(? ), suivie de trois nombres \d{3}, suivis de zéro ou une parenthèse de fermeture \)?, suivie d'un tiret, d'une barre oblique (slash) ou d'un point, conserve le caractère ([-\/\.]), suivi de trois chiffres \d{3}, suivi d'un second caractère de séparation identique au premier \1, suivi de quatre chiffres \d{4}.

L'événement Change, activé quand l'utilisateur appuie sur entrée, initialise la valeur de RegExp.input.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//FR"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <meta http-equiv="Content-Script-Type" content="text/javascript">
    <script type="text/javascript">
      var re = /\(?\d{3}\)?([-\/\.])\d{3}\1\d{4}/;

      function testInfo(phoneInput)
      {
        var OK = re.exec(phoneInput.value);

        if (!OK)
        {
          window.alert(RegExp.input + " n'est pas un numéro de téléphone valide !");
        }
        else
        {
          window.alert("Merci, votre numéro de téléphone est " + OK[0]);
        }
      }
    </script>
  </head>

  <body>
    <p>Entrez votre numéro de téléphone (ainsi que votre code régional) et appuyez sur Entrée.</p>
    <form action="">
      <input name="phone" onchange="testInfo(this);">
    </form>
  </body>
</html>