Outils d'utilisateurs

Outils du Site


expressions_regulieres_3

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_3 [2014/07/12 13:26]
gbdivers
expressions_regulieres_3 [2019/01/30 21:56] (Version actuelle)
alavida [Réutiliser un groupe de capture]
Ligne 1: Ligne 1:
  
-^ [[expressions_regulieres_2|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[comparer_strings|Chapitre suivant]] ^+^ [[expressions_regulieres_2|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[validation_motifs|Chapitre suivant]] ^
  
-====== Les expressions régulières ======+====== [Aller plus loin] Les expressions régulières ======
  
 ===== Les groupes de capture ===== ===== Les groupes de capture =====
  
-Les groupes de capture permet de réutiliser une sous-chaîne de la séquence cible, identifiée par un motif. Un groupe de capture s'écrire tout simplement entre parenthèses. Pour que cela soit plus clair, voyons quelques exemples. +Les groupes de capture permettent de réutiliser une sous-chaîne de la séquence cible, identifiée par un motif. La sous-chaîne capturée peut être réutilisée dans le motif ou être récupérée dans le code C++. Pour créer un groupe de capture, vous devez simplement écrire le motif correspondant à ce groupe entre parenthèses. Pour que cela soit plus clair, voyons quelques exemples. 
  
-==== Répéter un groupe ==== +==== Répéter un groupe de capture ====
- +
-Premièrement, groupe sans capture. (ab)* +
- +
-==== Réutiliser un groupe dans un motif ==== +
- +
- +
-Imaginons que vous souhaitez écrire un motif qui reconnaît la même lettre répétée trois fois, comme par exemple <html>"aaa"</html> ou <html>"fff"</html>. En première intention, vous pourriez écrire le motif suivant : <html>"[[:alpha:]]{3}"</html>. Ce motif est équivalent au motif suivant : <html>"[[:alpha:]][[:alpha:]][[:alpha:]]"</html>, donc une série de trois lettres. Cependant, il n'y a pas de contrainte sur les lettres, c'est-à-dire que rien n'oblige à ce que les deuxième et troisième lettres soient identiques à la première. Ainsi, par exemple, la chaîne <html>"abc"</html> correspond à ce motif. +
- +
-La solution est donc d'écrire un groupe de capture pour la première lettre et de réutiliser ce groupe trois fois. Le motif devient donc le suivant : <html>"([[:alpha:]]){3}"</html>. +
- +
-==== Sous groupes de capture ====+
  
 +Commençons par un exemple simple de groupe, sans utiliser la capture (donc sans réutiliser la sous-chaîne identifiée par le groupe). Le but est d'écrire un motif qui permet de valider une chaîne constituée de répétition la chaîne <html>"ab"</html>, comme par exemple <html>"ab"</html> ou <html>"ababab"</html>. En première intention, on pourrait être tenté d'écrire le motif suivant : <html>"ab*"</html>.
  
 +Cependant, le caractère de répétition <html>*</html> s'applique que sur le caractère <html>b</html>. Pour indiquer que l'on souhaite répéter le motif <html>"ab"</html>, il faut donc le mettre entre parenthèses : <html>"(ab)*"</html>.
  
 <code cpp main.cpp> <code cpp main.cpp>
-    { +#include &lt;iostream&gt
-        std::regex pattern(&quot;(ab)cd(ef)&quot;);    // Find double word. +#include &lt;regex&gt
-        std::string replacement = &quot;le premier groupe est $1 et le second groupe est $2&quot;;  +  
-        std::string target = "abcdef"; +int main() 
-        std::string output_str = regex_replace(target, pattern, replacement); +{ 
-        std::cout << output_str << std::endl; +    std::regex pattern { "ab*}
-    +    std::cout << "'ab*' match with '': " << std::boolalpha <<  
-    { +        std::regex_match("", pattern) << std::endl; 
-        std::regex pattern(R"((\d{2})[-/](\d{2})[-/](\d{4}))"); +  
-        std::smatch match; +    std::cout << "'ab*' match with 'ab': " << std::boolalpha <<  
-        std::regex_search(std::string("12-03-2014"), match, pattern)+        std::regex_match("ab", pattern) << std::endl; 
-        for (size_t i = 0; i < match.size(); ++i)  +  
-        { +    std::cout << "'ab*' match with 'abab': " << std::boolalpha &lt;&lt;  
-            std::cout << i << ": " << match[i].str() << '\n'; +        std::regex_match("abab", pattern) &lt;&ltstd::endl &lt;&ltstd::endl; 
-        }   +  
-    } +    pattern = "(ab)*"; 
-      +    std::cout &lt;&lt; "'(ab)*match with '': " &lt;&lt; std::boolalpha <<  
-    std::cout << "Traduction" << std::endl; +        std::regex_match("", pattern) << std::endl; 
-    { +  
-        std::regex pattern("([a-zA-Z]+) \\1");     +    std::cout << "'(ab)*' match with 'ab': " << std::boolalpha <<  
-        std::string replacement = "$1";      +        std::regex_match("ab", pattern) << std::endl; 
-        std::string target = "The cat cat bites the dog dog."; +  
-        std::string output_str = regex_replace(target, pattern, replacement)+    std::cout << "'(ab)*' match with 'abab': " << std::boolalpha <<  
-        std::cout << output_str << std::endl; +        std::regex_match("abab", pattern) << 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(&quot;&quot;, R"((ab)*)")+
-    match("a", R"((ab)*)&quot;); +
-    match(&quot;b&quot;, R&quot;((ab)*)")+
-    match("ab", R"((ab)*)")+
-    match(&quot;abc&quot;, R"((ab)*)"); +
-    match("ababab&quot;, R&quot;((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>
 +
 +affiche :
  
 <code> <code>
-Groups +'ab*' match with ''false 
-le premier groupe est ab et le second groupe est ef +'ab*' match with 'ab'true 
-012-03-2014 +'ab*' match with 'abab'false
-112 +
-203 +
-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 "" = true +'(ab)*match with 'ab': true 
-"(ab)*match with "a" = false +'(ab)*match with 'abab': true 
-"(ab)*" match with "b" = false +&lt;/code&gt;
-"(ab)*match with "ab" = true +
-&quot;(ab)*&quotmatch with "abc" = false +
-"(ab)*" match with "ababab" = true+
  
-"c[a-z]*t" match with "cat" = true 
  
-Exemples de regex +==== Réutiliser un groupe de capture ====
-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 +Les chaînes identifiées par un groupe de capture peuvent être réutilisées dans le motifChaque groupe est identifié par un numéro, dans l'ordre de leur déclarationPour réutiliser une chaîne, il faut indiquer le numéro de groupe précédé d'une barre oblique inversée : <html>\1</html>, <html>\2</html>, <html>\3</html>, etc.
-my.cmd +
-</code>+
  
-===== Manque vorace =====+Par exemple, pour écrire un motif qui permet d'identifier n'importe quelle chaîne commençant et terminant par le même caractère, on pourra écrire le motif suivant :
  
-__ A déplacer dans le chapitre sur les recherches ? __+  * pour récupérer le premier caractère : <html>(.)</html> ; 
 +  * pour les caractères de la chaîne autre que le premier et le dernier caractère : <html>.*</html> ; 
 +  * pour le dernier caractère, qui doit être identique au premier : <html>\1</html>.
  
-<code cpp main.cpp>     +Donc le motif final est <html>(.).*\1</html>. Pour écrire ce motif en C++, n'oubliez pas qu'il faut ajouter un caractère d'échappement devant la barre oblique inversée (le motif s'écrit alors <html>"(.).*\\1"</html>) ou il faut écrire une littérale chaîne brute (le motif s'écrit alors <html>R"((.).*\1)"</html>). 
-     // non-greedy (non vorace+ 
-    search("aaaaa", R"(a{3})");     // -&gtaaaaa = plus longue correspondance +<code cpp main.cpp> 
-    search("aaaaa", R"(a{3}?)");    // -&gtaaa = plus courte correspondance +#include <iostream> 
-    std::cout << std::endl;+#include <regex> 
 +  
 +int main() 
 +{ 
 +    std::regex const pattern { R"((.).*\1)}; 
 +    std::cout << "'(.).*\\1' match with '': << std::boolalpha <<  
 +        std::regex_match("", pattern<;&lt; std::endl; 
 +  
 +    std::cout << "'(.).*\\1' match with 'abc': << std::boolalpha <<  
 +        std::regex_match("abc", pattern) << std::endl; 
 +  
 +    std::cout << "'(.).*\\1' match with 'aba': << std::boolalpha <<  
 +        std::regex_match("aba", pattern<;&lt; std::endl; 
 +  
 +    std::cout << "'(.).*\\1' match with 'abcdefa': " << std::boolalpha <<  
 +        std::regex_match("abcdefa", pattern) << std::endl;
 } }
 </code> </code>
Ligne 140: Ligne 91:
  
 <code> <code>
-search "a{3}" in "aaaaa" = true +'(.).*\1' match with '': false 
-search "a{3}?" in "aaaaa" = true+'(.).*\1' match with 'abc': false 
 +'(.).*\1' match with 'aba': true 
 +'(.).*\1' match with 'abcdefa': true
 </code> </code>
  
-^ [[expressions_regulieres_2|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[comparer_strings|Chapitre suivant]] ^+De la même façon, si on veut pouvoir identifier une chaîne qui commence par deux caractères et qui se termine par ces deux caractères dans l'ordre inverse, on va pouvoir utiliser deux groupes de capture. Le motif s'écrit alors : <html>(.)(.).*\2\1</html>. 
 + 
 +Pour terminer avec les groupes de capture, ils vont permettre de récupérer dans le code C++ une sous-chaîne correspondant à un motif complet de la chaîne. En effet, imaginons que l'on souhaite écrire un motif qui permet de reconnaître une date au format <html>jj/mm/aa</html> (jour-mois-année, chaque élément étant écrit avec deux chiffres) et qui permet de récupérer le jour. On pourrait écrire simplement le motif <html>^[[:digit:]]{2}</html> (ou <html>^\d{2}</html>). Le problème est que ce motif peut correspondre à n'importe quelle chaîne commençant par deux chiffre (pour rappel, le caractère <html>^</html> est une ancre indiquant le début de la séquence cible), par exemple <html>"12abcde"</html> ou <html>"123456"</html>. 
 + 
 +Pour éviter cela, on va simplement écrire un motif qui correspond à une date, selon le format indiqué : <html>\d{2}/\d{2}/\d{2}</html>. On ajoute ensuite un groupe de capture pour les sous-chaînes que l'on souhaite récupérer dans le code C++. Par exemple, pour récupérer les jours, on écrit : <html>(\d{2})/\d{2}/\d{2}</html>. Cela permet de récupérer la date du jour, en garantissant que le format de date est respecté. 
 + 
 +Nous verrons par la suite le code C++ utilisé pour récupérer les groupes capturés. 
 + 
 +^ [[expressions_regulieres_2|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[validation_motifs|Chapitre suivant]] ^
  
-{{tag> Cours C++}} 
expressions_regulieres_3.1405164404.txt.gz · Dernière modification: 2014/07/12 13:26 par gbdivers