Outils d'utilisateurs

Outils du Site


expressions_regulieres

Différences

Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.

Lien vers cette vue

expressions_regulieres [2014/07/08 19:00]
gbdivers
expressions_regulieres [2016/07/05 18:54] (Version actuelle)
gbdivers
Ligne 1: Ligne 1:
  
-^ [[string_etendu|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[comparer_strings|Chapitre suivant]] ^+^ [[string_etendu|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[expressions_regulieres_2|Chapitre suivant]] ^
  
-====== Les expressions régulières ======+====== [Aller plus loin] Les expressions régulières ======
  
-Lorsque nous lisons un texte, nous sommes capable de reconnaître la signification (ou sémantique) de certains motifs dans le texte. Par exemple, si on écrit "25/12/2014", beaucoup de personnes reconnaîtront une date, correspondant au 25 décembre 2014. Si on écrit "18:30", on reconnaît une heure : dix-huit heure trente. Ou encore, on reconnait que "http://www.google.fr" est une URL internet.+Lorsque nous lisons un texte, nous sommes capable de reconnaître la signification (ou sémantique) de certains motifs dans le texte. Par exemple, si on écrit ''"25/12/2014"'', beaucoup de personnes reconnaîtront une date, correspondant au 25 décembre 2014. Si on écrit ''"18:30"'', on reconnaît une heure : dix-huit heure trente. Ou encore, on reconnait que ''"http://www.google.fr"'' est une URL internet.
  
-Nous sommes capable de trouver la sémantique d'un chaîne parce que l'on connaît le motif qui caractérise cette chaîne. On a l'habitude d'écrire les dates en indiquant le jour, le mois et l'année (en français). On a l'habitude aussi de voir des URL écrites sous la forme "http:/ /" suivi de plusieurs mots séparés par des points ou des barres obliques.+Nous sommes capable de trouver la sémantique d'une chaîne parce que l'on connaît le motif qui caractérise cette chaîne. On a l'habitude d'écrire les dates en indiquant le jour, le mois et l'année (en français). On a l'habitude aussi de voir des URL écrites sous la forme ''"http:/ /"'' suivi de plusieurs mots séparés par des points ou des barres obliques.
  
-Les expressions régulières sont un moyen efficace d'écrire de tels motifs. Avec ces motifs, il sera ensuite possible de vérifier qu'un chaîne respecte ce motif ou encore identifier les sous-chaînes qui respectent ce motif.+Les expressions régulières sont un moyen efficace d'écrire de tels motifs. Avec ces motifs, il sera ensuite possible de vérifier qu'une chaîne respecte ce motif ou encore d'identifier les sous-chaînes qui respectent ce motif.
  
 ===== Création et initialisation ===== ===== Création et initialisation =====
  
-__ origine du terme "expression régulière" ? __+__ Origine du terme "expression régulière" ? __
  
 Les expressions régulières sont une fonctionnalité que l'on trouve dans beaucoup de langages de programmation modernes. En C++, une expression régulière correspond à la classe ''regex'' de la bibliothèque standard (dans le fichier d'en-tête ''regex''). Il est possible de créer une expression régulière directement à partir d'une littérale chaîne de caractères ou d'une variable chaîne de type ''string''. Les expressions régulières sont une fonctionnalité que l'on trouve dans beaucoup de langages de programmation modernes. En C++, une expression régulière correspond à la classe ''regex'' de la bibliothèque standard (dans le fichier d'en-tête ''regex''). Il est possible de créer une expression régulière directement à partir d'une littérale chaîne de caractères ou d'une variable chaîne de type ''string''.
Ligne 33: Ligne 33:
 Pour bien comprendre les expressions régulières, il faut donner quelques définitions : Pour bien comprendre les expressions régulières, il faut donner quelques définitions :
  
-  * une **séquence cible** (//target sequence//) est la chaîne de caractères sur laquelle est appliqué l'expression régulière.+  * une **séquence cible** (//target sequence//) est la chaîne de caractères sur laquelle est appliquée l'expression régulière.
   * un **motif** (//pattern//) est la séquence de caractères représentant ce que l'on cherche à identifier.   * un **motif** (//pattern//) est la séquence de caractères représentant ce que l'on cherche à identifier.
   * une **correspondance** (//match//) est une sous-chaîne de la séquence cible qui correspond au motif.   * une **correspondance** (//match//) est une sous-chaîne de la séquence cible qui correspond au motif.
Ligne 39: Ligne 39:
 Plus concrètement, si l'on prend la chaîne suivante : "La date du 25/12/2014 est un jeudi" et que l'on demande d'écrire une expression régulière pour trouver la date dans cette chaîne, alors la chaîne "La date du 25/15/2014 est un jeudi" est la séquence cible et la correspondance est "25/12/2014". Le motif est une chaîne qui signifie "trouver une date au format jour/mois/année". Bien sûr, il n'est pas possible d'écrire un motif de cette façon, il faut utiliser une syntaxe spécifique, qui sera décrite dans la suite de ce chapitre. Plus concrètement, si l'on prend la chaîne suivante : "La date du 25/12/2014 est un jeudi" et que l'on demande d'écrire une expression régulière pour trouver la date dans cette chaîne, alors la chaîne "La date du 25/15/2014 est un jeudi" est la séquence cible et la correspondance est "25/12/2014". Le motif est une chaîne qui signifie "trouver une date au format jour/mois/année". Bien sûr, il n'est pas possible d'écrire un motif de cette façon, il faut utiliser une syntaxe spécifique, qui sera décrite dans la suite de ce chapitre.
  
-Avec une expression régulière, on va donc pouvoir réaliser principalement trois opérations, chaque opération correspondant à une fonction. Ces différentes fonctions seront détaillées par dans les prochains chapitres, la suite de ce chapitre sera consacré à la syntaxe utilisable pour écrire un motif. Mais pour vous permettre de pratiquer et apprendre correctement les expressions régulières, nous allons voir rapidement une syntaxe possible de ces fonctions (il est possible d'utiliser ces fonctions de différentes façon, nous n'en verrons qu'une seule pour le moment).+Avec une expression régulière, on va donc pouvoir réaliser principalement trois opérations, chaque opération correspondant à une fonction. Ces différentes fonctions seront détaillées dans les prochains chapitres, la suite de ce chapitre sera consacrée à la syntaxe utilisable pour écrire un motif. Mais pour vous permettre de pratiquer et apprendre correctement les expressions régulières, nous allons voir rapidement une syntaxe possible de ces fonctions (il est possible d'utiliser ces fonctions de différentes façons, nous n'en verrons qu'une seule pour le moment).
  
 La première fonctionnalité des expressions régulières est la **validation** d'une chaîne, c'est-à-dire vérifier qu'une chaîne respecte un motif. La fonction correspondante est la fonction ''regex_match''. Une version simple de cette fonction prend en arguments la séquence cible et l'expression régulière et retourne une valeur booléenne (vrai si la séquence cible correspond au motif, faux sinon). La première fonctionnalité des expressions régulières est la **validation** d'une chaîne, c'est-à-dire vérifier qu'une chaîne respecte un motif. La fonction correspondante est la fonction ''regex_match''. Une version simple de cette fonction prend en arguments la séquence cible et l'expression régulière et retourne une valeur booléenne (vrai si la séquence cible correspond au motif, faux sinon).
Ligne 56: Ligne 56:
          
     target = "abc";     target = "abc";
-    result = std::regex_match("abc", pattern);+    result = std::regex_match(target, pattern);
     std::cout << std::boolalpha << result << std::endl;     std::cout << std::boolalpha << result << std::endl;
 } }
Ligne 85: Ligne 85:
          
     target = "abc";     target = "abc";
-    result = std::regex_search("abc", pattern);+    result = std::regex_search(target, pattern);
     std::cout << std::boolalpha << result << std::endl;     std::cout << std::boolalpha << result << std::endl;
 } }
Ligne 97: Ligne 97:
 </code> </code>
  
-Le code est le même que précédemment, en remplaçant ''regex_match'' par ''regex_search''. Par contre, le résultat est très différent : la séquence cible "abcdef" ne correspondait pas au motif lorsque l'on utilise ''regex_match'', mais il correspond en utilisant ''regex_search'' (il existe bien le motif "abc" dans la séquence "abcdef").+Le code est le même que précédemment, en remplaçant ''regex_match'' par ''regex_search''. Par contre, le résultat est très différent : la séquence cible ''"abcdef"'' ne correspondait pas au motif lorsque l'on utilise ''regex_match'', mais il correspond en utilisant ''regex_search'' (il existe bien le motif ''"abc"'' dans la séquence ''"abcdef"'').
  
 Pour terminer, la troisième utilisation principales des expressions est le remplacement des sous-chaînes correspondant à un motif par d'autres chaînes. La fonction correspondante est ''regex_replace'', qui prend en argument la séquence cible, l'expression régulière (comme pour les précédentes fonctions) et la chaîne de remplacement, puis retourne la chaîne après modifications. Pour terminer, la troisième utilisation principales des expressions est le remplacement des sous-chaînes correspondant à un motif par d'autres chaînes. La fonction correspondante est ''regex_replace'', qui prend en argument la séquence cible, l'expression régulière (comme pour les précédentes fonctions) et la chaîne de remplacement, puis retourne la chaîne après modifications.
Ligne 122: Ligne 122:
 </code> </code>
  
-Ce qui correspond bien à la chaîne "abcdefabc", en remplaçant les sous-chaînes"abc" par "123".+Ce qui correspond bien à la chaîne ''"abcdefabc"'', en remplaçant les sous-chaînes ''"abc"'' par ''"123"''.
  
-===== La syntaxe des motifs ===== +===== Les différentes syntaxes possibles =====
- +
-==== Les différentes syntaxes possibles ====+
  
 Maintenant que vous avez une idée générale du fonctionnement des expressions régulières, il va falloir apprendre à écrire des motifs. La syntaxe à utiliser n'est pas très compliquée quand on a l'habitude, mais elle est écrite sous forme assez compacte dans une chaîne, ce qui ne facilite pas la lecture. Il ne faut donc pas hésiter à s'attarder un peu sur ce chapitre et pratiquer un maximum d'exercices, le temps de bien assimiler la syntaxe des expressions régulières. Maintenant que vous avez une idée générale du fonctionnement des expressions régulières, il va falloir apprendre à écrire des motifs. La syntaxe à utiliser n'est pas très compliquée quand on a l'habitude, mais elle est écrite sous forme assez compacte dans une chaîne, ce qui ne facilite pas la lecture. Il ne faut donc pas hésiter à s'attarder un peu sur ce chapitre et pratiquer un maximum d'exercices, le temps de bien assimiler la syntaxe des expressions régulières.
Ligne 145: Ligne 143:
 La liste des syntaxes acceptées par ''std::regex'' est disponible dans la [[http://en.cppreference.com/w/cpp/regex/basic_regex|documentation de cette classe]]. Par défaut, c'est la syntaxe ECMAScript qui est utilisée, nous utiliserons donc uniquement cette syntaxe dans ce cours. Mais sachez que d'autres syntaxes sont possibles.</note> La liste des syntaxes acceptées par ''std::regex'' est disponible dans la [[http://en.cppreference.com/w/cpp/regex/basic_regex|documentation de cette classe]]. Par défaut, c'est la syntaxe ECMAScript qui est utilisée, nous utiliserons donc uniquement cette syntaxe dans ce cours. Mais sachez que d'autres syntaxes sont possibles.</note>
  
-==== Visualiser les expressions régulières ====+===== Visualiser les expressions régulières =====
  
 Lorsque l'on débute avec les expressions régulières, il est parfois plus facile de visualiser le motif sous forme graphique. Si vous êtes plus à l'aise pour apprendre de cette façon, il existe des outils qui permettent de générer une représentation graphique à partir d'une expression régulière. Lorsque l'on débute avec les expressions régulières, il est parfois plus facile de visualiser le motif sous forme graphique. Si vous êtes plus à l'aise pour apprendre de cette façon, il existe des outils qui permettent de générer une représentation graphique à partir d'une expression régulière.
Ligne 153: Ligne 151:
 {{ :regex1.png |}} {{ :regex1.png |}}
  
-Ce graphique se lit de gauche vers la droite, il suffit de suivre les chemins possibles pour lire ce motif. Ce motif est donc constitué de trois groupes séparé par les caractères ''-'' ou ''/''. Chaque groupe est constitué de chiffres ("digit") répété 2 fois pour les deux premiers groupes et 4 fois pour le dernier groupe.+Ce graphique se lit de gauche vers la droite, il suffit de suivre les chemins possibles pour lire ce motif. Ce motif est donc constitué de trois groupes séparés par les caractères ''-'' ou ''/''. Chaque groupe est constitué de chiffres ("digit") répété 2 fois pour les deux premiers groupes et 4 fois pour le dernier groupe.
  
 L'ensemble des graphiques de ce cours pour les expressions régulières sont générés automatiquement par le site http://www.regexper.com/ et sont sous licence Creative Common (CC BY 3.0). L'ensemble des graphiques de ce cours pour les expressions régulières sont générés automatiquement par le site http://www.regexper.com/ et sont sous licence Creative Common (CC BY 3.0).
  
-==== Les caractères de base ====+===== Les caractères de base =====
  
 La forme la plus simple de motif est constitué de caractères alphanumériques de base (a, b, E, G, 3, 7, etc). Chaque caractère du motif est recherché dans la séquence cible à l'identique. Ainsi, le motif "abc" permettra de rechercher dans une chaîne cette séquence exacte. La forme la plus simple de motif est constitué de caractères alphanumériques de base (a, b, E, G, 3, 7, etc). Chaque caractère du motif est recherché dans la séquence cible à l'identique. Ainsi, le motif "abc" permettra de rechercher dans une chaîne cette séquence exacte.
Ligne 191: Ligne 189:
 </code> </code>
  
-Ainsi, le motif "a" ne peut correspondre sur si la séquence cible correspond exactement à "a", les chaînes "", "b" et "ab" ne correspondent pas.+Ainsi, le motif "a" ne peut correspondre que si la séquence cible correspond exactement à "a", les chaînes "", "b" et "ab" ne correspondent pas.
  
 Attention de bien faire attention à la fonction que l'on utilise. Si on réalise une recherche de sous-chaînes (avec ''regex_search'') au lieu d'une validation de chaîne (avec ''regex_match''), le résultat obtenu n'est pas identique. Attention de bien faire attention à la fonction que l'on utilise. Si on réalise une recherche de sous-chaînes (avec ''regex_search'') au lieu d'une validation de chaîne (avec ''regex_match''), le résultat obtenu n'est pas identique.
Ligne 220: Ligne 218:
 Dans le premier cas, la chaîne "ab" ne correspond pas au motif "a" (elles ne sont pas identiques). Dans le second cas, le motif "a" est retrouvé dans le chaîne "ab" (la séquence cible contient le motif). Dans le premier cas, la chaîne "ab" ne correspond pas au motif "a" (elles ne sont pas identiques). Dans le second cas, le motif "a" est retrouvé dans le chaîne "ab" (la séquence cible contient le motif).
  
-Il est possible d'utiliser la grande majorité des caractères dans un motif (même des caractères étrangers, ce point sera détaillé dans la partie "Internationalisation"). Cependant, certain caractères on une signification particulière (que vous verrez par la suite) dans un motif et ne peuvent être utilisé directement.+Il est possible d'utiliser la grande majorité des caractères dans un motif (même des caractères étrangers, ce point sera détaillé dans la partie "Internationalisation"). Cependant, certains caractères ont une signification particulière (que vous verrez par la suite) dans un motif et ne peuvent être utilisé directement.
  
 Imaginons que vous souhaitez par exemple vérifier qu'une chaîne contient un point. Vous pourriez écrire le code suivant par exemple : Imaginons que vous souhaitez par exemple vérifier qu'une chaîne contient un point. Vous pourriez écrire le code suivant par exemple :
Ligne 253: Ligne 251:
 __ pas clair, à réécrire __ __ pas clair, à réécrire __
  
-Donc la recherche réussit dans les deux, alors que la première séquence cible ne contient pas de point. La raison est que le point est un caractère spécial et ne permet pas de rechercher un point dans la séquence cible. Pour rechercher le caractère point ''.'', il faut le faire précéder du caractère barre oblique inversé ''\''. Le motif pour rechercher un point dans une chaîne est donc "\." et non pas simplement ".".+Donc la recherche réussit dans les deux, alors que la première séquence cible ne contient pas de point. La raison est que le point est un caractère spécial et ne permet pas de rechercher un point dans la séquence cible. Pour rechercher le caractère point ''.'', il faut le faire précéder du caractère barre oblique inversée ''\''. Le motif pour rechercher un point dans une chaîne est donc "\." et non pas simplement ".".
  
-Cependant, le caractère barre oblique inversé possède également un signification particulière en C++. On l'appelle le caractère d'échappement. Il permet d'entrer un caractère spéciale, comme les tabulations ou les retours à la ligne (comme vu dans les chapitres précédents). Ce caractère d'échappement s'associe avec le caractère qui le suit pour ne former qu'un seul caractère. Ainsi, '\n' ou '\n' ne sont pas deux caractères (\ puis n) mais bien un seul (si vous essayer d'écrire '/n', vous obtiendrez une erreur, puisqu'il n'est pas possible de mettre deux caractères dans une littérale caractère. Par contre '\n' ne pose pas de problème puisque c'est considéré comme un seul caractère).+Cependant, le caractère barre oblique inversée possède également un signification particulière en C++. On l'appelle le caractère d'échappement. Il permet d'entrer un caractère spéciale, comme les tabulations ou les retours à la ligne (comme vu dans les chapitres précédents). Ce caractère d'échappement s'associe avec le caractère qui le suit pour ne former qu'un seul caractère. Ainsi, '\n' ou '\n' ne sont pas deux caractères (\ puis n) mais bien un seul (si vous essayer d'écrire '/n', vous obtiendrez une erreur, puisqu'il n'est pas possible de mettre deux caractères dans une littérale caractère. Par contre '\n' ne pose pas de problème puisque c'est considéré comme un seul caractère).
  
-Pour écrire le caractère '\', il faut donc écrire '\\' en C++, ce qui fait que le motif "\." devient "\\." en C++. Cette chaîne doit être lue de la façon suivante : le premier \ correspond au caractère d'échappement, donc \\ correspond au caractère \ dans le motif, et donc le motif \. permet de rechercher un point.+Pour écrire le caractère ''\'', il faut donc écrire ''\\'' en C++, ce qui fait que le motif ''"\."'' devient ''"\\."'' en C++. Cette chaîne doit être lue de la façon suivante : le premier ''"\"'' correspond au caractère d'échappement, donc ''"\\"'' correspond au caractère ''"\"'' dans le motif, et donc le motif ''"\."'' permet de rechercher un point.
  
-Une autre solution en C++, pour éviter de devoir utiliser les caractères d'échappement, est d'utiliser les littérales chaînes brutes (//raw string//). Dans ce cas, les caractères spéciaux du C++ (\ ou " par exemple) sont interprété comme des caractères normaux. Pour écrire une littérale chaîne brute, il faut remplacer "..." par R"(...)"+Une autre solution en C++, pour éviter de devoir utiliser les caractères d'échappement, est d'utiliser les littérales chaînes brutes (//raw string//). Dans ce cas, les caractères spéciaux du C++ (''\'' ou ''"'' par exemple) sont interprété comme des caractères normaux. Pour écrire une littérale chaîne brute, il faut remplacer ''"..."'' par ''R"(...)"''.
  
-Ainsi, au lieu d'écrire "\\.", il est possible d'écrire R"(\.)". le code devient alors :+Ainsi, au lieu d'écrire ''"\\."'', il est possible d'écrire ''R"(\.)"''. le code devient alors :
  
 <code cpp main.cpp> <code cpp main.cpp>
Ligne 288: Ligne 286:
 </code> </code>
  
-Les caractères spéciaux des expressions régulières, qu'il faut ajouter \ sont les suivants :+Les caractères spéciaux des expressions régulières, qu'il faut ajouter ''\'' sont les suivants :
  
 ^ Caractère utilisé dans les motifs ^ Caractère recherché dans la séquence cible ^ ^ Caractère utilisé dans les motifs ^ Caractère recherché dans la séquence cible ^
Ligne 306: Ligne 304:
 |  ''\|''                           |  ''|''                                     | |  ''\|''                           |  ''|''                                     |
  
-==== Caractère générique, classe de caractères et ensemble de caractères ==== 
- 
-Chaque caractère de base correspond à un seul caractère dans la séquence terminale, mais il est parfois nécessaire de pouvoir exprimer dans un motif que l'on souhaite n'importe quel caractère issu d'un ensemble. Par exemple, pour créer un motif permettant de valider une date, il faut pouvoir écrire que l'on souhaite avoir n'importe quelle chiffre. Peut importe le chiffre, du moment que c'est un chiffre. Les caractères génériques, classes de caractères et ensembles de caractères permettent d'écrire cela. 
- 
-Le caractère générique correspond au point dans une expression régulière. Il signifie "n'importe quel caractère", mais uniquement un seul caractère. Par exemple, le motif "ab.de" peut correspondre aux chaînes "abcde" ou "ab$de", mais pas à la chaîne "ab$$de". 
- 
-<note info>Ceci explique pourquoi, dans le code précédent, le motif "." était retrouvé dans n'importe quelle chaîne, puisque cela signifie simple "trouve un caractère quelconque dans la chaîne". Donc seule la chaîne vide "" retourne faux avec ce motif.</note> 
- 
-<code cpp main.cpp> 
-#include <iostream> 
-#include <string> 
-#include <regex> 
-  
-int main() 
-{ 
-    std::regex pattern { "." }; 
-    std::cout << "'.' match with '': " << std::boolalpha <<  
-        std::regex_match("", pattern) << std::endl; 
-         
-    std::cout << "'.' match with 'a': " << std::boolalpha <<  
-        std::regex_match("a", pattern) << std::endl; 
-         
-    std::cout << "'.' match with 'ab': " << std::boolalpha <<  
-        std::regex_match("ab", pattern) << std::endl; 
-         
-    pattern = "abc"; 
-    std::cout << "'abc' match with 'abc': " << std::boolalpha <<  
-        std::regex_match("abc", pattern) << std::endl; 
-         
-    std::cout << "'abc' match with 'a$c': " << std::boolalpha <<  
-        std::regex_match("a$c", pattern) << std::endl; 
-         
-    pattern = "a.c"; 
-    std::cout << "'a.c' match with 'abc': " << std::boolalpha <<  
-        std::regex_match("abc", pattern) << std::endl; 
-         
-    std::cout << "'a.c' match with 'a$c': " << std::boolalpha <<  
-        std::regex_match("a$c", pattern) << std::endl; 
-} 
-</code> 
- 
-affiche : 
- 
-<code> 
-'.' match with '': false 
-'.' match with 'a': true 
-'.' match with 'ab': false 
-'abc' match with 'abc': true 
-'abc' match with 'a$c': false 
-'a.c' match with 'abc': true 
-'a.c' match with 'a$c': true 
-</code> 
- 
-On voit donc bien que la chaîne correspond au motif uniquement si elle ne contient un et un seul caractère, pas plus, pas moins. 
- 
-Les ensembles de caractères (//character set//) permettent de représenter une liste de caractères entre crochets droits ''[]''. Chaque ensemble permet de remplacer un et un seul caractère. Par exemple, le motif "[abc]" représente un seul caractère, qui peut être a, b ou c. 
- 
-<code cpp main.cpp> 
-#include <iostream> 
-#include <string> 
-#include <regex> 
-  
-int main() 
-{ 
-    std::regex const pattern { "[abc]" }; 
-    std::cout << "'[abc]' match with '': " << std::boolalpha <<  
-        std::regex_match("", pattern) << std::endl; 
-         
-    std::cout << "'[abc]' match with 'a': " << std::boolalpha <<  
-        std::regex_match("a", pattern) << std::endl; 
-         
-    std::cout << "'[abc]' match with 'b': " << std::boolalpha <<  
-        std::regex_match("b", pattern) << std::endl; 
-         
-    std::cout << "'[abc]' match with 'z': " << std::boolalpha <<  
-        std::regex_match("z", pattern) << std::endl; 
-         
-    std::cout << "'[abc]' match with 'ab': " << std::boolalpha <<  
-        std::regex_match("ab", pattern) << std::endl; 
-} 
-</code> 
- 
-affiche : 
- 
-<code> 
-'[abc]' match with '': false 
-'[abc]' match with 'a': true 
-'[abc]' match with 'b': true 
-'[abc]' match with 'z': false 
-'[abc]' match with 'ab': false 
-</code> 
- 
-Si l'on souhaite écrire un motif qui permet de valider n'importe quelle lettre minuscule ou n'importe quel chiffre, il est fastidieux d'écrire tous les caractères correspondant : "[abcdefghijklmnopqrstuvwxyz]" et "[0123456789]". Pour éviter cela, il est possible de spécifier une plage de valeur en indiquant le premier et le dernier caractère de la plage, séparés par un tiret. Par exemple : "[a-z]" ou "[0-9]". 
- 
-<code cpp main.cpp> 
-#include <iostream> 
-#include <string> 
-#include <regex> 
-  
-int main() 
-{ 
-    std::regex pattern { "[a-e]" }; 
-    std::cout << "'[a-e]' match with '': " << std::boolalpha <<  
-        std::regex_match("", pattern) << std::endl; 
-         
-    std::cout << "'[a-e]' match with 'a': " << std::boolalpha <<  
-        std::regex_match("a", pattern) << std::endl; 
-         
-    std::cout << "'[a-e]' match with 'e': " << std::boolalpha <<  
-        std::regex_match("e", pattern) << std::endl; 
-         
-    std::cout << "'[a-e]' match with 'z': " << std::boolalpha <<  
-        std::regex_match("z", pattern) << std::endl; 
-         
-    std::cout << "'[a-e]' match with 'ab': " << std::boolalpha <<  
-        std::regex_match("ab", pattern) << std::endl; 
-         
-    pattern = "ab[c-f]"; 
-    std::cout << "'ab[c-f]' match with '': " << std::boolalpha <<  
-        std::regex_match("", pattern) << std::endl; 
-         
-    std::cout << "'ab[c-f]' match with 'abc': " << std::boolalpha <<  
-        std::regex_match("abc", pattern) << std::endl; 
-         
-    std::cout << "'ab[c-f]' match with 'abz': " << std::boolalpha <<  
-        std::regex_match("abz", pattern) << std::endl; 
-} 
-</code> 
-     
-affiche : 
- 
-<code> 
-'[a-e]' match with '': false 
-'[a-e]' match with 'a': true 
-'[a-e]' match with 'e': true 
-'[a-e]' match with 'z': false 
-'[a-e]' match with 'ab': false 
-'ab[c-f]' match with '': false 
-'ab[c-f]' match with 'abc': true 
-'ab[c-f]' match with 'abz': false 
-</code> 
- 
-Il est possible de spécifier plusieurs plages dans un ensemble, par exemple "[a-er-z]" correspond à un caractère qui peut être a, b, c, d, e, r, s, t, u, v, w, x, y ou z. 
- 
-Certains ensembles de classes sont souvent utilisées, il existe donc des raccourcis pour éviter de les réécrire à chaque fois. Ce sont les classes de caractères (//character class//). Par exemple, le motif "[[:alpha:]]" correspond à n'importe quel caractère alphabétique, donc est équivalent à "[a-zA-Z]". Le tableau suivant présente l'ensemble des classes de caractères possible : 
- 
-^ Classe de caractères ^ Description                       ^ Ensemble équivalent                         ^ 
-|  ''[:alnum:]''       | Caractères alphanumériques        |  ''[a-zA-Z0-9]''                            | 
-|  ''[:alpha:]''       | Caractères alphabétiques          |  ''[a-zA-Z]''                               | 
-|  ''[:ascii:]''       | Caractères ASCII                  |  ''[\x00-\x7F]''                            | 
-|  ''[:blank:]''       | Espace et tabulation              |  ''[ \t]''                                  | 
-|  ''[:cntrl:]''       | Caractères de contrôle            |  ''[\x00-\x1F\x7F]''                        | 
-|  ''[:digit:]''       | Chiffres                          |  ''[0-9]''                                  |  
-|  ''[:graph:]''       | Caractères visibles               |  ''[\x21-\x7E]''                            | 
-|  ''[:lower:]''       | Caractères minuscules             |  ''[a-z]''                                  | 
-|  ''[:print:]''       | Caractères visibles et espace     |  ''[\x20-\x7E]''                            | 
-|  ''[:punct:]''       | Ponctuation et symboles           |  ''[!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]''  | 
-|  ''[:space:]''       | Caractères blancs                 |  ''[ \t\r\n\v\f]''                          | 
-|  ''[:upper:]''       | Caractères majuscules             |  ''[A-Z]''                                  | 
-|  ''[:word:]''        | Lettre, chiffre ou tiret bas      |  ''[A-Za-z0-9_]''                           | 
-|  ''[:xdigit:]''      | Chiffres hexadécimaux             |  ''[A-Fa-f0-9]''                            | 
- 
- 
- 
- 
-<code cpp main.cpp>     
-    match("a", R"([[:alpha:]])"); 
-    match("1", R"([[:alpha:]])"); 
-    match("&", R"([[:alpha:]])"); 
-    match("a", R"([[:alnum:]])"); // alnum = alphanumeric 
-    match("1", R"([[:alnum:]])"); 
-    match("&", R"([[:alnum:]])"); 
-    std::cout << "Autres : alnum ou w, alpha, blank, cntrl, digit ou d, graph, lower,\n" 
-        "    print, punct, space ou s, upper, xdigit (digit hexa)" << std::endl; 
-    std::cout << std::endl; 
-     
-    // escape notation 
-    // \d  = [[:d:]] 
-    // \D = [^[:d:]] 
-    // \s = [[:s:]] 
-    // \S = [^[:s:]] 
-    // \w = [[:w:]] 
-    // \W = [^[:w:]] 
-     
-    std::cout << "Répétition" << std::endl; 
-    match("", R"(a*)"); // zero or more 
-    match("a", R"(a*)"); 
-    match("aa", R"(a*)"); 
-    match("aaaaaa", R"(a*)"); 
-    match("b", R"(a*)"); 
-    search("jdsihbhvdsv", R"(a*)"); 
-    std::cout << std::endl; 
-     
-    match("", R"(a+)"); // one or more 
-    match("a", R"(a+)"); 
-    match("aa", R"(a+)"); 
-    match("aaaaaa", R"(a+)"); 
-    match("b", R"(a+)"); 
-    std::cout << std::endl; 
-     
-    match("", R"(a?)"); // zero or one 
-    match("a", R"(a?)"); 
-    match("aa", R"(a?)"); 
-    std::cout << std::endl; 
-     
-    match("", R"(a{3})"); // bounded repeat 
-    match("a", R"(a{3})"); 
-    match("aaa", R"(a{3})"); 
-    match("aaaaa", R"(a{3})"); 
-    match("", R"(a{3,})"); 
-    match("a", R"(a{3,})"); 
-    match("aaa", R"(a{3,})"); 
-    match("aaaaa", R"(a{3,})"); 
-    match("", R"(a{3,5})"); 
-    match("a", R"(a{3,5})"); 
-    match("aaa", R"(a{3,5})"); 
-    match("aaaaa", R"(a{3,5})"); 
-    match("aaaaaaa", R"(a{3,5})"); 
-    std::cout << std::endl; 
-      
-     // non-greedy (non vorace) 
-    search("aaaaa", R"(a{3})");     // -> aaaaa = plus longue correspondance 
-    search("aaaaa", R"(a{3}?)");    // -> aaa = plus courte correspondance 
-    std::cout << std::endl; 
-     
-    std::cout << "Ancres (anchor)" << std::endl; 
-    search("", R"(^a)"); // début 
-    search("a", R"(^a)"); 
-    search("abc", R"(^a)"); 
-    search("cba", R"(^a)"); 
-    std::cout << std::endl; 
-     
-    search("", R"(a$)"); // fin 
-    search("a", R"(a$)"); 
-    search("abc", R"(a$)"); 
-    search("cba", R"(a$)"); 
-    std::cout << std::endl; 
-     
-    std::cout << "Groupes (group)" << std::endl; 
-    std::cout << "Priorité des opérateurs (precedence)" << std::endl; 
-} 
-</code> 
- 
-affiche : 
- 
-<code> 
-Caractères de base 
-"a" match with "" = false 
-"a" match with "a" = true 
-"a" match with "b" = false 
-"a" match with "ab" = false 
-"ab" match with "ab" = true 
-"ab" match with "abb" = false 
- 
-différence entre match et search 
-"a" match with "ab" = false 
-search "a" in "ab" = true 
- 
-Caractères générique (wildcard) 
-"." match with "" = false 
-"." match with "a" = true 
-"." match with "abc" = false 
- 
-"abc" match with "abc" = true 
-"abc" match with "a5c" = false 
-"a.c" match with "abc" = true 
-"a.c" match with "a5c" = true 
- 
-"[[:alpha:]]" match with "a" = true 
-"[[:alpha:]]" match with "1" = false 
-"[[:alpha:]]" match with "&" = false 
-"[[:alnum:]]" match with "a" = true 
-"[[:alnum:]]" match with "1" = true 
-"[[:alnum:]]" match with "&" = false 
-Autres : alnum ou w, alpha, blank, cntrl, digit ou d, graph, lower, 
-    print, punct, space ou s, upper, xdigit (digit hexa) 
- 
-Ensemble de caractères (character set) 
-"[ab]" match with "" = false 
-"[ab]" match with "a" = true 
-"[ab]" match with "b" = true 
-"[ab]" match with "ab" = false 
- 
-"[a-e]" match with "" = false 
-"[a-e]" match with "a" = true 
-"[a-e]" match with "e" = true 
-"[a-e]" match with "f" = false 
-"[a-e]" match with "ab" = false 
- 
-"ab[c-f]" match with "" = false 
-"ab[c-f]" match with "abc" = true 
- 
-Répétition 
-"a*" match with "" = true 
-"a*" match with "a" = true 
-"a*" match with "aa" = true 
-"a*" match with "aaaaaa" = true 
-"a*" match with "b" = false 
-search "a*" in "jdsihbhvdsv" = true 
- 
-"a+" match with "" = false 
-"a+" match with "a" = true 
-"a+" match with "aa" = true 
-"a+" match with "aaaaaa" = true 
-"a+" match with "b" = false 
- 
-"a?" match with "" = true 
-"a?" match with "a" = true 
-"a?" match with "aa" = false 
- 
-"a{3}" match with "" = false 
-"a{3}" match with "a" = false 
-"a{3}" match with "aaa" = true 
-"a{3}" match with "aaaaa" = false 
-"a{3,}" match with "" = false 
-"a{3,}" match with "a" = false 
-"a{3,}" match with "aaa" = true 
-"a{3,}" match with "aaaaa" = true 
-"a{3,5}" match with "" = false 
-"a{3,5}" match with "a" = false 
-"a{3,5}" match with "aaa" = true 
-"a{3,5}" match with "aaaaa" = true 
-"a{3,5}" match with "aaaaaaa" = false 
- 
-search "a{3}" in "aaaaa" = true 
-search "a{3}?" in "aaaaa" = true 
- 
-Ancres (anchor) 
-search "^a" in "" = false 
-search "^a" in "a" = true 
-search "^a" in "abc" = true 
-search "^a" in "cba" = false 
- 
-search "a$" in "" = false 
-search "a$" in "a" = true 
-search "a$" in "abc" = false 
-search "a$" in "cba" = true 
- 
-Groupes (group) 
-Priorité des opérateurs (precedence) 
-</code> 
- 
-<code cpp main.cpp> 
-#include <iostream> 
-#include <string> 
-#include <regex> 
- 
-void search(std::string const& target, std::string const& pattern_str) { 
-    std::regex pattern { pattern_str }; 
-    std::cout << R"(search ")" << pattern_str << R"(" in ")" << target << R"(" = )"   
-        << std::boolalpha << std::regex_search(target, pattern) << std::endl; 
-} 
- 
-void match(std::string const& target, std::string const& pattern_str) { 
-    std::regex pattern { pattern_str }; 
-    std::cout << R"(")" << pattern_str << R"(" match with ")" << target << R"(" = )" 
-        << std::boolalpha << std::regex_match(target, pattern) << std::endl; 
-} 
- 
-std::string tr(std::string const& s, int i) { 
-    return std::regex_replace(s, std::regex(R"(\$\d)"), std::to_string(i)); 
-} 
-  
-int main() 
-{     
-    std::cout << "Groups" << std::endl; 
-    { 
-        std::regex pattern("(ab)cd(ef)");    // Find double word. 
-        std::string replacement = "le premier groupe est $1 et le second groupe est $2";  
-        std::string target = "abcdef"; 
-        std::string output_str = regex_replace(target, pattern, replacement); 
-        std::cout << output_str << std::endl; 
-    } 
-    { 
-        std::regex pattern(R"((\d{2})[-/](\d{2})[-/](\d{4}))"); 
-        std::smatch match; 
-        std::regex_search(std::string("12-03-2014"), match, pattern); 
-        for (size_t i = 0; i < match.size(); ++i)  
-        { 
-            std::cout << i << ": " << match[i].str() << '\n'; 
-        }   
-    } 
-      
-    std::cout << "Traduction" << std::endl; 
-    { 
-        std::regex pattern("([a-zA-Z]+) \\1");     
-        std::string replacement = "$1";      
-        std::string target = "The cat cat bites the dog dog."; 
-        std::string output_str = regex_replace(target, pattern, replacement); 
-        std::cout << output_str << std::endl; 
-    } 
-     
-    std::cout << tr("bla bla $1 bla bla", 123) << std::endl; 
-    std::cout << tr("bli bli bli bli $1", 123) << std::endl; 
-    std::cout << std::endl; 
-     
-     
-    std::cout << "Groupe" << std::endl; 
-    match("", R"((ab)*)"); 
-    match("a", R"((ab)*)"); 
-    match("b", R"((ab)*)"); 
-    match("ab", R"((ab)*)"); 
-    match("abc", R"((ab)*)"); 
-    match("ababab", R"((ab)*)"); 
-    std::cout << std::endl; 
-     
-     
-    match("cat", R"(c[a-z]*t)"); 
-    std::cout << std::endl; 
-     
-    std::cout << "Exemples de regex" << std::endl; 
-    std::cout << "Date" << std::endl; 
-    match("12-03-2014", R"(\d{2}[-/]\d{2}[-/]\d{4})"); 
-    std::cout << "Time" << std::endl; 
-    match("15:17", R"(\d{2}:\d{2})"); 
-    std::cout << std::endl; 
-     
-    // vérifier qu'un identifiant C++ est valide 
-    // [a-zA-Z_][a-zA-Z_0-9]* 
-     
-    // fichier windows 
-    //[a-zA-Z_][a-zA-Z_0-9]*\.[a-zA-Z0-9]+ 
-     
-    std::string regex_str = "[a-z_][a-z_0-9]*\\.[a-z0-9]+"; 
-    std::regex reg1(regex_str, std::regex_constants::icase); 
-    std::string str = "File names are readme.txt and my.cmd."; 
-    std::sregex_iterator it(str.begin(), str.end(), reg1); 
-    std::sregex_iterator it_end; 
-    while(it != it_end) { 
-        std::cout << it->str() << std::endl; 
-        ++it; 
-    } 
-} 
-</code> 
- 
-<code> 
-Groups 
-le premier groupe est ab et le second groupe est ef 
-0: 12-03-2014 
-1: 12 
-2: 03 
-3: 2014 
-Traduction 
-The cat bites the dog. 
-bla bla 123 bla bla 
-bli bli bli bli 123 
- 
-Groupe 
-"(ab)*" match with "" = true 
-"(ab)*" match with "a" = false 
-"(ab)*" match with "b" = false 
-"(ab)*" match with "ab" = true 
-"(ab)*" match with "abc" = false 
-"(ab)*" match with "ababab" = true 
- 
-"c[a-z]*t" match with "cat" = true 
- 
-Exemples de regex 
-Date 
-"\d{2}[-/]\d{2}[-/]\d{4}" match with "12-03-2014" = true 
-Time 
-"\d{2}:\d{2}" match with "15:17" = true 
- 
-readme.txt 
-my.cmd 
-</code> 
  
-^ [[string_etendu|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[comparer_strings|Chapitre suivant]] ^+^ [[string_etendu|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[expressions_regulieres_2|Chapitre suivant]] ^
  
-{{tag> Cours C++}} 
expressions_regulieres.1404838832.txt.gz · Dernière modification: 2014/07/08 19:00 (modification externe)