Je vais essayer d'expliquer cela à l'aide d'un exemple.
Considérez le texte suivant :
http://stackoverflow.com/
https://stackoverflow.com/questions/tagged/regex
Maintenant, si j'applique la regex ci-dessous sur elle ...
(https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?
... J'obtiendrais le résultat suivant :
Match "http://stackoverflow.com/"
Group 1: "http"
Group 2: "stackoverflow.com"
Group 3: "/"
Match "https://stackoverflow.com/questions/tagged/regex"
Group 1: "https"
Group 2: "stackoverflow.com"
Group 3: "/questions/tagged/regex"
Mais je ne me soucie pas du protocole - je veux juste l'hôte et le chemin de l'URL. Donc, je change la regex pour inclure le groupe non capturant (?:)
.
(?:https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?
Maintenant, mon résultat ressemble à ceci :
Match "http://stackoverflow.com/"
Group 1: "stackoverflow.com"
Group 2: "/"
Match "https://stackoverflow.com/questions/tagged/regex"
Group 1: "stackoverflow.com"
Group 2: "/questions/tagged/regex"
Vous voyez ? Le premier groupe n'a pas été saisi. L'analyseur syntaxique l'utilise pour faire correspondre le texte, mais l'ignore ensuite, dans le résultat final.
EDITAR:
Comme demandé, permettez-moi d'essayer d'expliquer aussi les groupes.
Les groupes ont plusieurs fonctions. Ils peuvent vous aider à extraire des informations exactes d'une correspondance plus importante (qui peut également être nommée), ils vous permettent de faire correspondre à nouveau un groupe correspondant précédent, et peuvent être utilisés pour des substitutions. Essayons quelques exemples, d'accord ?
Imaginez que vous avez une sorte de fichier XML ou HTML (sachez que regex n'est peut-être pas le meilleur outil pour ce travail mais c'est un bon exemple). Vous voulez analyser les balises, vous pourriez donc faire quelque chose comme ceci (j'ai ajouté des espaces pour faciliter la compréhension) :
\<(?<TAG>.+?)\> [^<]*? \</\k<TAG>\>
or
\<(.+?)\> [^<]*? \</\1\>
La première regex a un groupe nommé (TAG), tandis que la seconde utilise un groupe commun. Les deux regex font la même chose : elles utilisent la valeur du premier groupe (le nom de la balise) pour faire correspondre la balise de fermeture. La différence est que la première utilise le nom pour faire correspondre la valeur, tandis que la seconde utilise l'index du groupe (qui commence à 1).
Essayons maintenant quelques substitutions. Considérons le texte suivant :
Lorem ipsum dolor sit amet consectetuer feugiat fames malesuada pretium egestas.
Maintenant, utilisons cette stupide regex sur ça :
\b(\S)(\S)(\S)(\S*)\b
Cette regex correspond à des mots comportant au moins 3 caractères, et utilise des groupes pour séparer les trois premières lettres. Le résultat est le suivant :
Match "Lorem"
Group 1: "L"
Group 2: "o"
Group 3: "r"
Group 4: "em"
Match "ipsum"
Group 1: "i"
Group 2: "p"
Group 3: "s"
Group 4: "um"
...
Match "consectetuer"
Group 1: "c"
Group 2: "o"
Group 3: "n"
Group 4: "sectetuer"
...
Donc, si nous appliquons la chaîne de substitution :
$1_$3$2_$4
... par-dessus, nous essayons d'utiliser le premier groupe, d'ajouter un trait de soulignement, d'utiliser le troisième groupe, puis le deuxième groupe, d'ajouter un autre trait de soulignement, puis le quatrième groupe. La chaîne résultante serait comme celle ci-dessous.
L_ro_em i_sp_um d_lo_or s_ti_ a_em_t c_no_sectetuer f_ue_giat f_ma_es m_la_esuada p_er_tium e_eg_stas.
Vous pouvez également utiliser des groupes nommés pour les substitutions, en utilisant les éléments suivants ${name}
.
Pour jouer avec les regex, je recommande http://regex101.com/ qui offre une bonne quantité de détails sur le fonctionnement des regex ; il propose également quelques moteurs de regex parmi lesquels choisir.
70 votes
Cette question a été ajoutée à la FAQ sur les expressions régulières de Stack Overflow sous la rubrique "Groupes".