JavaRush /Blog Java /Random-FR /RegEx : 20 petites étapes pour maîtriser les expressions ...
Artur
Niveau 40
Tallinn

RegEx : 20 petites étapes pour maîtriser les expressions régulières. Partie 3

Publié dans le groupe Random-FR
RegEx : 20 petites étapes pour maîtriser les expressions régulières. Partie 1. RegEx : 20 petites étapes pour maîtriser les expressions régulières. Partie 2 : Dans cette partie, nous passerons à des choses un peu plus complexes. Mais les maîtriser, comme avant, ne sera pas difficile. Je répète que RegEx est en réalité plus facile qu’il n’y paraît au premier abord, et vous n’avez pas besoin d’être un génie pour le maîtriser et commencer à l’utiliser dans la pratique. L'original anglais de cet article est ici . 20 petites étapes pour maîtriser les expressions régulières.  Partie 3 - 1

Étape 11 : Parenthèses ()comme groupes de capture

20 petites étapes pour maîtriser les expressions régulières.  Partie 3 - 2Dans le dernier problème, nous avons recherché différents types de valeurs entières et de valeurs numériques à virgule flottante (point). Mais le moteur d'expression régulière ne faisait pas de différence entre ces deux types de valeurs, puisque tout était capturé dans une grande expression régulière. Nous pouvons demander au moteur d'expressions régulières de différencier les différents types de correspondances si nous mettons nos mini-modèles entre parenthèses :
modèle : ([AZ])|([az]) 
chaîne :   L'actuel président de la Bolivie est Evo Morales .
matchs : ^^^ ^^^^^^^ ^^^^^^^^^ ^^ ^^^^^^^ ^^ ^^^ ^^^^^^^ 
groupe :    122 2222222 122222222 22 1222222 22 122 1222222  
( Exemple ) L'expression régulière ci-dessus définit deux groupes de capture indexés à partir de 1. Le premier groupe de capture correspond à n'importe quelle lettre majuscule et le deuxième groupe de capture correspond à n'importe quelle lettre minuscule. En utilisant le signe « ou » |et les parenthèses ()comme groupe de capture, nous pouvons définir une seule expression régulière qui correspond à plusieurs types de chaînes. Si nous appliquons cela à notre expression régulière de recherche longue/flottante de la partie précédente de l'article, alors le moteur d'expression régulière capturera les correspondances correspondantes dans les groupes appropriés. En vérifiant à quel groupe correspond une sous-chaîne, nous pouvons immédiatement déterminer s'il s'agit d'une valeur flottante ou d'une valeur longue :
motif : (\d*\.\d+[fF]|\d+\.\d*[fF]|\d+[fF])|(\d+[lL]) 
chaîne :   42L 12 x 3.4f 6l 3.3 0F LF .2F0 .
matchs : ^^^ ^^^^ ^^ ^^ ^^^ 
groupe :    222 1111 22 11 111  
( Exemple ) Cette expression régulière est assez complexe, et pour mieux la comprendre, décomposons-la et examinons chacun de ces modèles :
( // correspond à n'importe quelle sous-chaîne "float"
  \d*\.\d+[fF]
  |
  \d+\.\d*[fF]
  |
  \d+[fF]
)
| //OU
( // correspond à n'importe quelle sous-chaîne "longue"
  \d+[lL]
)
Le signe |et les groupes de capture entre parenthèses ()nous permettent de faire correspondre différents types de sous-chaînes. Dans ce cas, nous faisons correspondre soit des nombres à virgule flottante "float", soit des entiers longs "long".
(
  \d*\.\d+[fF] // 1+ chiffres à droite de la virgule décimale
  |
  \d+\.\d*[fF] // 1+ chiffres à gauche de la virgule décimale
  |
  \d+[fF] // pas de point, seulement 1+ chiffres
)
|
(
  \d+[lL] // pas de point, seulement 1+ chiffres
)
Dans le groupe de capture « flottant », nous avons trois options : les nombres avec au moins 1 chiffre à droite de la virgule décimale, les nombres avec au moins 1 chiffre à gauche de la virgule décimale et les nombres sans virgule décimale. Tous sont des « flottants » tant qu'ils comportent les lettres « f » ou « F » ajoutées à la fin. Dans le groupe de capture "long", nous n'avons qu'une seule option : nous devons avoir 1 ou plusieurs chiffres suivis du caractère "l" ou "L". Le moteur d'expression régulière recherchera ces sous-chaînes dans une chaîne donnée et les indexera dans le groupe de capture approprié. noteque nous ne correspondons à aucun des nombres auxquels aucun des "l", "L", "f" ou "F" n'est ajouté. Comment classer ces chiffres ? Eh bien, s'ils ont un point décimal, le langage Java est par défaut "double". Sinon, ils doivent être "int".

Consolidons ce que nous avons appris avec quelques énigmes :

Ajoutez deux groupes de capture supplémentaires à l'expression régulière ci-dessus afin qu'elle classe également les nombres doubles ou entiers. (C'est une autre question délicate, ne vous découragez pas si cela prend du temps, en dernier recours, voyez ma solution.)
modèle:
chaîne :   42L 12 x 3,4f 6l 3,3 0F LF .2F 0. 
correspondances : ^^^ ^^ ^^^^ ^^ ^^^ ^^ ^^^ ^^ 
groupe :    333 44 1111 33 222 11 111 22
( Solution ) Le problème suivant est un peu plus simple. Utilisez les groupes de capture entre parenthèses (), le signe « ou » |et les plages de caractères pour trier les âges suivants : « il est légal de boire aux États-Unis ». (>= 21) et « interdiction de boire aux États-Unis » (<21) :
modèle:
chaîne :   7 10 17 18 19 20 21 22 23 24 30 40 100 120 
correspondances : ^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^ 
groupe :    2 22 22 22 22 22 11 11 11 11 11 11 111 111 
( Solution )

Étape 12 : Identifiez d’abord les correspondances plus spécifiques

20 petites étapes pour maîtriser les expressions régulières.  Partie 3 - 3Vous avez peut-être eu quelques problèmes avec la dernière tâche si vous avez essayé de définir les « buveurs légaux » comme le premier groupe de capture plutôt que le second. Pour comprendre pourquoi, regardons un autre exemple. Supposons que nous souhaitions enregistrer séparément les noms de famille contenant moins de 4 caractères et les noms de famille contenant 4 caractères ou plus. Donnons des noms plus courts au premier groupe de capture et voyons ce qui se passe :
motif : ([AZ][az]?[az]?)|([AZ][az][az][az]+) 
chaîne :   Kim Job s Xu Clo yd Moh r Ngo Roc k.
matchs : ^^^ ^^^ ^^ ^^^ ^^^ ^^^ ^^^ 
groupe :    111 111 11 111 111 111 111   
( Exemple ) Par défaut, la plupart des moteurs d'expressions régulières utilisent une correspondance gourmande avec les caractères de base que nous avons vus jusqu'à présent. Cela signifie que le moteur d'expression régulière capturera le groupe le plus long défini le plus tôt possible dans l'expression régulière fournie. Ainsi, bien que le deuxième groupe ci-dessus puisse capturer plus de caractères dans des noms tels que « Jobs » et « Cloyd » par exemple, étant donné que les trois premiers caractères de ces noms ont déjà été capturés par le premier groupe de capture, ils ne peuvent pas être capturés à nouveau par le second. . Faisons maintenant une petite correction : changez simplement l'ordre des groupes de capture, en plaçant le groupe le plus spécifique (le plus long) en premier :
modèle : ([AZ][az][az][az]+)|([AZ][az]?[az]?) 
chaîne :   Kim Jobs Xu Cloyd Mohr Ngo Rock .
matchs : ^^^ ^^^^ ^^ ^^^^^ ^^^^ ^^^ ^^^^ 
groupe :    222 1111 22 11111 1111 222 1111    
( Exemple )

Tâche... cette fois une seule :)

Un motif « plus spécifique » signifie presque toujours « plus long ». Disons que nous voulons trouver deux types de « mots » : d'abord ceux qui commencent par des voyelles (plus précisément), puis ceux qui ne commencent pas par des voyelles (n'importe quel autre mot). Essayez d'écrire une expression régulière pour capturer et identifier les chaînes qui correspondent à ces deux groupes. (Les groupes ci-dessous sont lettrés plutôt que numérotés. Vous devez déterminer quel groupe doit correspondre au premier et lequel au second.)
modèle:
chaîne :   pds6f uub 24r2gp ewqrty l ui_op 
correspondances : ^^^^^ ^^^ ^^^^^^ ^^^^^^ ^ ^^^^^ 
groupe :    NNNNN VVV NNNNNN VVVVVV N VVVVV
( Solution ) En général, plus votre expression régulière est précise, plus elle sera longue. Et plus c’est précis, moins il est probable que vous capturiez quelque chose dont vous n’avez pas besoin. Ainsi, même si elles peuvent paraître effrayantes, les expressions rationnelles plus longues ~ = de meilleures expressions rationnelles. Malheureusement .

Étape 13 : accolades {}pour un nombre spécifique de répétitions

20 petites étapes pour maîtriser les expressions régulières.  Partie 3 - 4Dans l'exemple avec les noms de famille de l'étape précédente, nous avions 2 groupes presque répétitifs dans un seul modèle :
modèle : ([AZ][az][az][az]+)|([AZ][az]?[az]?) 
chaîne :   Kim Jobs Xu Cloyd Mohr Ngo Rock .
matchs : ^^^ ^^^^ ^^ ^^^^^ ^^^^ ^^^ ^^^^ 
groupe :    222 1111 22 11111 1111 222 1111    
Pour le premier groupe, nous avions besoin de noms de famille comportant quatre lettres ou plus. Le deuxième groupe devait saisir les noms de famille comportant trois lettres ou moins. Existe-t-il un moyen plus simple d’écrire ceci que de répéter ces [a-z]groupes encore et encore ? Existe si vous utilisez des accolades pour cela {}. Les accolades {}nous permettent de spécifier le nombre minimum et (éventuellement) maximum de correspondances du caractère ou du groupe de capture précédent. Il existe trois cas d'utilisation{} :
{X} // correspond exactement X fois
{X,} // correspond >= X fois
{X,Y} // correspond à >= X et <= Y fois
Voici des exemples de ces trois syntaxes différentes :
modèle : [az]{11} 
chaîne :   humuhumunuk unukuapua'a.
correspondances : ^^^^^^^^^^^   
( Exemple )
modèle : [az]{18,} 
chaîne :   humuhumunukunukuapua 'a.
correspondances : ^^^^^^^^^^^^^^^^^^^^^    
( Exemple )
modèle : [az]{11,18} 
chaîne :   humuhumunukunukuap ua'a.
correspondances : ^^^^^^^^^^^^^^^^^^    
( Exemple ) Il y a plusieurs points à noter dans les exemples ci-dessus.note:. Tout d'abord, en utilisant la notation {X}, le caractère ou le groupe précédent correspondra exactement à ce nombre (X) fois. S'il y a plus de caractères dans le « mot » (que le nombre X) qui pourraient correspondre au modèle (comme indiqué dans le premier exemple), alors ils ne seront pas inclus dans la correspondance. Si le nombre de caractères est inférieur à X, la correspondance complète échouera (essayez de remplacer 11 par 99 dans le premier exemple). Deuxièmement, les notations {X,} et {X,Y} sont gourmandes. Ils essaieront de faire correspondre autant de caractères que possible tout en satisfaisant l'expression régulière donnée. Si vous spécifiez {3,7}, 3 à 7 caractères peuvent correspondre et si les 7 caractères suivants sont valides, les 7 caractères seront mis en correspondance. Si vous spécifiez {1,} et que tous les 14 000 caractères suivants correspondent, alors ces 14 000 caractères seront inclus dans la chaîne correspondante. Comment pouvons-nous utiliser ces connaissances pour réécrire notre expression ci-dessus ? L'amélioration la plus simple pourrait être de remplacer les groupes voisins [a-z]par [a-z]{N}, où N est choisi en conséquence :
modèle : ([AZ][az]{2}[az]+)|([AZ][az]?[az]?)  
... mais cela n'améliore pas vraiment les choses. Regardez le premier groupe de capture : nous avons [a-z]{2}(qui correspond exactement à 2 lettres minuscules) suivi de [a-z]+(qui correspond à 1 ou plusieurs lettres minuscules). Nous pouvons simplifier cela en demandant 3 lettres minuscules ou plus en utilisant des accolades :
modèle : ([AZ][az]{3,})|([AZ][az]?[az]?) 
Le deuxième groupe de capture est différent. Nous n'avons pas besoin de plus de trois caractères dans ces noms de famille, ce qui signifie que nous avons une limite supérieure, mais notre limite inférieure est zéro :
modèle : ([AZ][az]{3,})|([AZ][az]{0,2}) 
La spécificité est toujours meilleure lors de l'utilisation d'expressions régulières, il serait donc sage de s'arrêter là, mais je ne peux m'empêcher de remarquer que ces deux plages de caractères ( [AZ]et [az]) côte à côte ressemblent presque à une classe de "caractères de mots", \w( [A-Za-z0-9_]) . Si nous étions sûrs que nos données ne contenaient que des noms de famille bien formatés, nous pourrions alors simplifier notre expression régulière et écrire simplement :
modèle : (\w{4,})|(\w{1,3}) 
Le premier groupe capture toute séquence de 4 « caractères de mot » ou plus ( [A-Za-z0-9_]), et le deuxième groupe capture toute séquence de 1 à 3 « caractères de mot » (inclus). Est-ce que ça va marcher?
modèle : (\w{4,})|(\w{1,3}) 
chaîne :   Kim Jobs Xu Cloyd Mohr Ngo Rock .
matchs : ^^^ ^^^^ ^^ ^^^^^ ^^^^ ^^^ ^^^^ 
groupe :    222 1111 22 11111 1111 222 1111    
( Exemple ) Ça a marché ! Qu’en est-il de cette approche ? Et c'est beaucoup plus propre que notre exemple précédent. Puisque le premier groupe de capture correspond à tous les noms de famille comportant quatre caractères ou plus, nous pourrions même remplacer le deuxième groupe de capture par simplement \w+, car cela nous permettrait de capturer tous les noms de famille restants (avec 1, 2 ou 3 caractères) :
modèle : (\w{4,})|(\w+) 
chaîne :   Kim Jobs Xu Cloyd Mohr Ngo Rock .
matchs : ^^^ ^^^^ ^^ ^^^^^ ^^^^ ^^^ ^^^^ 
groupe :    222 1111 22 11111 1111 222 1111    
( Exemple )

Aidons le cerveau à apprendre cela et résolvons les 2 problèmes suivants :

Utilisez des accolades {}pour réécrire l'expression régulière de recherche de numéro de sécurité sociale de l'étape 7 :
modèle:
chaîne : 113-25=1902 182-82-0192 H23-_3-9982 1I1-O0-E38B
correspondances :              ^^^^^^^^^^^
( Solution ) Supposons que le vérificateur de force des mots de passe d'un site Web exige que les mots de passe des utilisateurs comportent entre 6 et 12 caractères. Écrivez une expression régulière qui signale les mots de passe invalides dans la liste ci-dessous. Chaque mot de passe est contenu entre parenthèses ()pour faciliter la correspondance. Assurez-vous donc que l'expression régulière commence et se termine par des caractères littéraux (et )symboliques. Astuce : assurez-vous d'interdire les parenthèses littérales dans les mots de passe avec [^()]ou similaires, sinon vous finirez par faire correspondre la chaîne entière !
modèle:
chaîne :   (12345) (mon mot de passe) (Xanadu.2112) (su_do) (OfSalesmen !)
correspondances : ^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^  
( Solution )

Étape 14 : \bSymbole de bordure de largeur nulle

20 petites étapes pour maîtriser les expressions régulières.  Partie 3 à 5La dernière tâche était assez difficile. Mais et si nous rendions les choses un peu plus compliquées en mettant les mots de passe entre guillemets ""au lieu de parenthèses ()? Pouvons-nous écrire une solution similaire en remplaçant simplement tous les caractères parenthèses par des guillemets ?
modèle : \"[^"]{0.5}\"|\"[^"]+\s[^"]*\" 
chaîne :   "12345" "mon mot de passe" "Xanadu.2112 " " su_do" " Des vendeurs ! "
correspondances : ^^^^^^^ ^^^^^^^^^^^^^ ^^^ ^^^  
( Exemple ) Cela ne s'est pas avéré très impressionnant. Avez-vous déjà deviné pourquoi ? Le problème est que nous recherchons ici des mots de passe incorrects. "Xanadu.2112" est un bon mot de passe, donc lorsque l'expression régulière se rend compte que cette séquence ne contient ni espaces ni caractères littéraux ", elle cède juste avant le caractère "qui qualifie le mot de passe sur le côté droit. (Parce que nous avons précisé que les caractères "ne peuvent pas être trouvés dans les mots de passe à l'aide de [^"].) Une fois que le moteur d'expression régulière est convaincu que ces caractères ne correspondent pas à une expression régulière particulière, il s'exécute à nouveau, exactement là où il s'était arrêté - là où se trouvait le caractère ". ce qui limite " Xanadu.2112" à droite. De là, il voit un caractère espace et un autre caractère "- pour lui, ce n'est pas le bon mot de passe ! En gros, il retrouve cette séquence " "et passe à autre chose. Ce n'est pas du tout ce que nous aimerions obtenir... Ce serait formidable si nous pouvions préciser que le premier caractère du mot de passe ne doit pas être un espace. Y a-t-il un moyen de faire cela? (À présent, vous avez probablement réalisé que la réponse à toutes mes questions rhétoriques est « oui ».) Oui ! Il existe un tel moyen ! De nombreux moteurs d'expressions régulières fournissent une séquence d'échappement telle que « limite de mot » \b. « Limite de mot » \best une séquence d'échappement de largeur nulle qui, curieusement, correspond à une limite de mot. N'oubliez pas que lorsque nous disons « mot », nous entendons soit n'importe quelle séquence de caractères de la classe \w, soit [A-Za-z0-9_]. Une correspondance de limite de mot signifie que le caractère immédiatement avant ou immédiatement après la séquence \bdoit être неun caractère de mot. Cependant, lors de la correspondance, nous n'incluons pas ce caractère dans notre sous-chaîne capturée. C'est une largeur nulle. Pour voir comment cela fonctionne, regardons un petit exemple :
pattern : \b[^ ]+\b 
string :   Je veux toujours de l'argent , Lebowski .
correspondances : ^^ ^^^^^ ^^^^ ^^ ^^^^^ ^^^^^^^^  
( Exemple ) La séquence [^ ]doit correspondre à tout caractère qui n'est pas un espace littéral. Alors pourquoi cela ne correspond-il pas à la virgule ,après argent ou au point " .après Lebowski ? En effet, la virgule ,et le point .ne sont pas des caractères de mots, donc des limites sont créées entre les caractères de mots et les caractères non-mots. Ils apparaissent entre yla fin du le mot money et la virgule ,qui le suit. et entre " ile mot Lebowski et le point .(point/point) qui le suit. L'expression régulière correspond aux limites de ces mots (mais pas aux caractères non-mots qui aident uniquement à les définir). Mais que se passe-t-il si nous n’incluons pas de cohérence \bdans notre modèle ?
motif : [^ ]+ 
chaîne :   Je veux toujours de l'argent, Lebowski. 
correspondances : ^^ ^^^^^ ^^^^ ^^ ^^^^^^ ^^^^^^^^^  
( Exemple ) Oui, maintenant nous trouvons aussi ces signes de ponctuation. Utilisons maintenant les limites de mots pour corriger l'expression régulière des mots de passe cités :
modèle : \"\b[^"]{0.5}\b\"|\"\b[^"]+\s[^"]*\b\" chaîne : "12345" 
"   mon mot de passe" " Xanadu. 2112" "su_do" "DesVendeurs !"
correspondances : ^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^  
( Exemple ) En plaçant les limites des mots entre guillemets ("\b ... \b"), nous disons en fait que le premier et le dernier caractères des mots de passe correspondants doivent être des "caractères de mots". Cela fonctionne donc bien ici, mais ne fonctionnera pas aussi bien si le premier ou le dernier caractère du mot de passe de l'utilisateur n'est pas un caractère de mot :
motif : \"\b[^"]{0,5}\b\"|\"\b[^"]+\s[^"]*\b\"
chaîne : "le mot de passe suivant est trop court" "C++"
allumettes:   
( Exemple ) Voyez comment le deuxième mot de passe n'est pas marqué comme "invalide" même s'il est clairement trop court. tu dois êtreprudentavec des séquences \b, car elles ne correspondent qu'aux limites entre les caractères \wet non \w. Dans l'exemple ci-dessus, puisque nous n'avons pas autorisé les caractères dans les mots de passe \w, la limite entre \le premier et le dernier caractère du mot de passe n'est pas garantie comme étant une limite de mot \b.

Pour réaliser cette étape, nous ne résoudrons qu’un seul problème simple :

Les limites de mots sont utiles dans les moteurs de coloration syntaxique lorsque nous voulons faire correspondre une séquence spécifique de caractères, mais que nous voulons nous assurer qu'elles n'apparaissent qu'au début ou à la fin d'un mot (ou seules). Disons que nous écrivons une coloration syntaxique et que nous souhaitons mettre en évidence le mot var, mais uniquement lorsqu'il apparaît seul (sans toucher aux autres caractères du mot). Pouvez-vous écrire une expression régulière pour cela ? Bien sûr que vous pouvez, c'est une tâche très simple ;)
modèle:
chaîne :   var varx _var ( var j) barvarcar * var var -> { var }
correspondances : ^^^ ^^^ ^^^ ^^^ ^^^  
( Solution )

Étape 15 : "caret" ^comme "début de ligne" et signe dollar $comme "fin de ligne"

20 petites étapes pour maîtriser les expressions régulières.  Partie 3 à 6La séquence de limite de mots \b(de la dernière étape de la partie précédente de l'article) n'est pas la seule séquence spéciale de largeur nulle disponible pour une utilisation dans les expressions régulières. Les deux plus populaires sont le « caret » ^– « début de ligne » et le signe dollar $– « fin de ligne ». En inclure un dans vos expressions régulières signifie que la correspondance doit apparaître au début ou à la fin de la chaîne source :
modèle : ^start|end$ 
chaîne :   début fin début fin début fin début fin 
correspondances : ^^^^^ ^^^  
( Exemple ) Si votre chaîne contient des sauts de ligne, elle ^startcorrespondra à la séquence "start" au début de n'importe quelle ligne, et end$correspondra à la séquence "end" à la fin de n'importe quelle ligne (bien que cela soit difficile à montrer ici). Ces symboles sont particulièrement utiles lorsque vous travaillez avec des données contenant des délimiteurs. Revenons au problème de la « taille du fichier » de l'étape 9 en utilisant ^le « début de ligne ». Dans cet exemple, nos tailles de fichiers sont séparées par des espaces " ". Nous souhaitons donc que chaque taille de fichier commence par un nombre, précédé d'un caractère espace ou d'un début de ligne :
modèle : (^| )(\d+|\d+\.\d+)[KMGT] 
Chaîne B :   6,6 Ko 1..3 Ko 12 Ko 5G 3,3 Mo Ko .6,2 To 9 Mo .
matchs : ^^^^^ ^^^^^ ^^^^^^ ^^^^ 
groupe :    222 122 1222 12    
( Exemple ) Nous sommes déjà si près du but ! Mais vous remarquerez peut-être que nous avons encore un petit problème : nous faisons correspondre le caractère espace avant la taille valide du fichier. Maintenant, nous pouvons simplement ignorer ce groupe de capture (1) lorsque notre moteur d'expression régulière le trouve, ou nous pouvons utiliser un groupe de non-capture, ce que nous verrons à l'étape suivante.

En attendant, résolvons 2 autres problèmes de tonalité :

En poursuivant notre exemple de coloration syntaxique de la dernière étape, certaines colorations syntaxiques marqueront les espaces de fin, c'est-à-dire tous les espaces situés entre un caractère autre qu'un espace et la fin de la ligne. Pouvez-vous écrire une expression régulière pour mettre en évidence uniquement les espaces de fin ?
modèle:
chaîne : myvec <- c(1, 2, 3, 4, 5)  
correspondances :                          ^^^^^^^  
( Solution ) Un simple analyseur de valeurs séparées par des virgules (CSV) recherchera des « jetons » séparés par des virgules. Généralement, l’espace n’a de sens que s’il est placé entre guillemets "". Écrivez une expression régulière d'analyse CSV simple qui fait correspondre les jetons entre virgules, mais ignore (ne capture pas) les espaces blancs qui ne sont pas entre guillemets.
modèle:
chaîne :   a, "b", "c d",e,f, "g h", dfgi,, k, "", l 
correspond à : ^^ ^^^^ ^^^^^^^^^^ ^^^ ^^^ ^^^^^^ ^^ ^^^ ^ 
groupe :    21 2221 2222212121 222221 222211 21 221 2    
( Solution ) RegEx : 20 petites étapes pour maîtriser les expressions régulières. Partie 4.
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION