More is less

02/09/2015

Regex en C++

Paradoxalement c'est en C++ que les expressions régulières sont les plus simples à employer. Il suffit de connaître la syntaxe ECMAScript et les trois méthodes regex_match, regex_search et regex_replace. Accessoirement nous utiliserons une nouveauté de C++11 : for x: conteneur

Sources

Le site cplusplus.com est certainement le plus clair et le plus documenté.

ECMAScript

C'est la syntaxe utilisé par défaut par C++. La syntaxe rappelle celle bash.

Les caractères spéciaux sont:

Exemples :

"^# (.*)$"
le caractère dièse au début, suivi d'un espce, suivi de n'importe quoi. Ce n'importe quoi forme un groupe référencé par $1.
Exemple # commentaire
"(\\+|\\-)? (.*)$"
Plus ou moins ou rien suivi d'espace puis n'importe quoi.
Exemple "+ Ligne n° 1".
Remarque le double anti slash n'en produit qu'un seul.
"\\[(.+?)->(.+?)\\]"
On voudrait bien quelque chose comme [lien->cible].
[zob->cul] est inconvenant, mais convient quand même.

regex_match

On souhaite reconnaitre une url http ou ftp.

L'expression régulière est "(http|ftp)://([^. ]+)\\.([^. ]+)\\.(.+)"

Elle se décompose ainsi :

(ftp|http) : groupe, concorde avec 'http' ou 'ftp'

:// : tel quel, ne constitue pas un groupe

([^. ]+) : groupe, correspond à un ou plusieurs caractères ni point ni espace. Remarque : entre [] il n'est pas nécessaire d'échapper le point

\\. : un point, ne constitue pas un groupe

([^. ]+) : déjà rencontrée. Dans [^. ] le circonflexe signifie non et pas début.

\\. : encore un point

(.+) : groupe, le reste de l'expression

Finalement la regex est "(http|ftp)://([^.]+)\\.([^.]+)\\.(.+)"

La syntaxe simple est regex_match(s, re) mais on emploie plus souvent la syntaxe regex(s, m, re) où s est la chaîne dans laquelle on cherche, re l'expression régulière et m de type smatch (ou cmatch) permet de récupérer les correspondances. Dans l'exemple ci-dessus, s'il y a correspondance, on aura :

m[0] : la chaîne entière

m[1] : ftp ou http

m[2] : vraisemblablement ftp ou www ou un sous domaine

m[3] : le nom du site

m[4] : le suffixe com fr net etc.

Source : regex_match.cpp

Autre exemple

Exemple permettant de reconnaitre la notation utilisée par lilypond pour représenter une note :

regex re("([a-g](?:es)?(?:is)?)([',]{0,3})([0-9]{0,3})([.]?)");

Une note est composée d'une lettre [a-g] suivie de 'is' ou 'es' suivie d'une apostrophe ou d'une virgule, suivie d'un nombre, suivi d'un point. Sauf la lettre de départ, tout le reste est facultatif.

regex_search

La différence avec match, est que search cherche à l'intérieur de la cible. Dans l'exemple ci-dessous on trouve deux occurences du patron recherché.

string = " { ais4 c. }"
smatch m;
regex_search(s, m, ex)

Les méthodes prefix() et suffix() permettent en plus connaître la chaîne qui précède la coïncidence et celle qui la suit.

A la fin du while, on exploite la méthode suffix() pour poursuivre la recherche.

Source : regex_search.cpp.

regex_replace

Fchier source : regex_replace.cpp

Commentaires

Réalisé avec Qlam - LGPL