Un outil bien utile: les expressions régulières
Applications:
Valider, rechercher ou remplacer du texte (dans DW: filtrer&nettoyer données).
Apparaissent dans:
langages de scripts/programmes UNIX: grep, sed, awk...
perl
PHP, javascript (valider input, reformater), SQL (pattern matching)
librairies dans langages de programmation: perl, python, java, c++...
parseurs, analyse de paquets dans les réseaux. . .
éditeurs de texte/IDE (Find&Replace))
Caveat:
Plusieurs ”standards”, fonctionnalités varient légèrement. Variantes principales:
variantes POSIX: Basic et Extended (BRE, ERE)
PCRE (originaires de Perl).
Les outils proposent de nombreuses options, mais varient beaucoup entre outils.
Moteurs de Regex:
PCRE, Oniguruma, RE2 (Google), Boost (C++), RegExp (Javascript). . .
Pour tester les regex des transparents suivants:
grep -E --color='auto' pattern <(printf 'text')
pcregrep --color='auto' pattern <(printf 'text')
[Link] 1
Expressions régulières: pense-bête
a symbole a Classes de caractères:
(r) r (délimiteur/capture) [ a1 ...an ] 1 caractère: a1 ou a2 ou...
r1 r2 r1 or r2 (alternative) [ a-d ] a, b, c ou d
r1 r2 concaténation [ˆ... ] tout caractère sauf ...
[\x00-\x7F] ASCII ([:ascii:] POSIX)
Caractères spéciaux:
. tout symbole (sauf \n) Classes de caractères prédéfinies (POSIX and PCRE):
ˆ début du texte Posix Description PCRE
$ fin du texte [:alpha:] [A-Za-z]
[:alnum:] [A-Za-z0-9]
d
Quantification:
[:digit:] [0-9] \d
r? 0 ou 1 occurrence de r [:space:] [\t\r\n\v\f]=espaces \s
r⇤ 0 ou plus occurrences [:blank:] espaces horizontaux \h
r+ 1 ou plus occurrences [:punct:] ponctuation
[:upper:] majuscule \u
r {n} exactement n occ.
[:word:] [A-Za-z0-9_] \w
r {n, } au moins n occ. [:print:] [\x20-\x7E]=car visibl+ espace
r {min, max} entre min et max occ. [= a =] classe d’équivalence de "a"
PCRE: maj. pour inverser: \D = non-chiffre.
Sous-expr capturées:
Métacaractères PCRE/ERE:
\n la sous-chaîne correspondant à la ˆ . [ ] $ ( ) * + ? | { } \ échappés par \
nième sous-expression capturée
Métacaractères pour BRE:
(définie par la nième parenthèse ouvrante) ˆ.[]$*\
[Link] 2
Expressions régulières: règles de comportement
Algorithme de recherche des occurrences:
par défaut, moteur POSIX cherche la première et plus longue occurrence. Moteur
PCRE cherche la première occurrence avec quantificateur glouton.
ancres et autres assertions (ˆ, $, \b, \B, (?= r ). . . ) ne “matchent” pas de symboles.
Classes de caractères:
classes de caract. POSIX s’utilisent entre “[ ]”: ex: [[:alpha:]]
classes de caract. prédéfinies déterminées par catégorie LC_CTYPE de la locale (UNIX)
classe d’équivalence [= a =] ' [aàáâäåãAÀ...] définie par cat. LC_COLLATE (UNIX).
attention aux digraphes, é peut être 1 ou 2 caractère, etc.
inclure des caract. spéciaux dans classe de caractère:
meta status est en général perdu dans une classe de caract.
quand - en premier ou dernier dans “[ ]” : pas intervalle mais symbole - lui-même.
classes jamais vides ni imbriquées, donc les crochets sont reconnus dans [a [ b] et [ ]ab]
Captures:
\0 capture toute le motif
parfois $n (hors motif) au lieu de \n (dans le motif) pour référence arrière
Métacaractères:
langages de scripts et programmation interprètent le motif avant de le passer au
moteur ) d’où double échappement! ) penser à échapper les symboles ex: ( ) \
préférez PCRE, ou au moins ERE: en BRE il faut échapper ( ) { }. De plus: BRE n’a
[Link] pas d’alternation |. Et \? \+ sont parfois supportés, mais pas standards. 3
Expressions régulières: règles de comportement (2)
L’ordre de priorité des opérateurs est le suivant:
1 Collation-related bracket symbols [==] [::] [..]
2 Escaped characters \
3 Character set (bracket expression) []
4 Grouping ()
5 Single-character-ERE duplication * + ? {m,n}
6 Concatenation
7 Anchoring ˆ$
8 Alternation |
[Link] 4
Expressions régulières: exemples
Exemples (PCRE ou ERE):
[a-z]+0 reconnaît texte contenant une ou plusieurs minuscules suivies de 0.
ˆ[0-9]{10}$ reconnaît texte (ligne) qui consiste en un nombre à 10 chiffres.
[ˆ0-9]{1,4} va sélectionner: 12ac34589:#@$45
[[:alpha:]]*[[:digit:]][ˆ[:alnum:],]+ va sélectionner: A#589:#@,aa$b45
(ab|cd)+ee|ˆab va sélectionner: abaacdzcdabeez
([a-c])z\1\1 reconnaît azaa mais pas azcc.
Find:
PCRE: (\d{4})-(\d{2})-(\d{2})
ERE (POSIX classes): ([[:digit:]]{4})-([[:digit:]]{2})-([[:digit:]]{2})
ERE: ([0-9]{4})-([0-9]{2})-([0-9]{2})
BRE: \([0-9]\{4\}\)-\([0-9]\{2\}\)-\([0-9]\{2\}\)
Replace: $3/$2/$1
[Link] 5
Expressions régulières PCRE: pense-bête (avancé)
Divers:
\b limite de mot (assertion, comme ˆ et $, et autres ancres: \< début de mot \> fin)
\B pas une limite de mot (ancre)
(?: r) groupe non-capturant
Assertions : ! si négative, = si positive, < pour en-arrière ( positive/neg. look-ahead/look-behind)
(?= r ) assertion avant positive
(?! r ) assertion avant négative
(?<= r ) assertion arrière positive
(?<! r ) assertion arrière négative
Motif conditionnel (seulement dans certains moteurs: python, perl, pcre)
(?( if ) then | else )
Capture nommée (pcre, python)
Capture Référence Remplacement
(?P< nomGroupe > r ) (?P= nomGroupe ) \g< nomGroupe > Python, Perl, ...
(?< nomGroupe > r ) \k< nomGroupe > ${ nomGroupe } .Net, Java
(?< nomGroupe > r ) \k< nomGroupe > $+{ nomGroupe } Perl
Références et remplacements peuvent aussi utiliser le numéro de groupe, ex: \1.
Options (pas standard, mais presque toujours proposées sous une forme ou une autre)
i insensible à la casse
m multiline: si le texte a des symboles, ˆ et $ reconnaissent extrémités de chaque ligne
s single-line: permet à “.” de reconnaître symbole newline
x expanded: espaces seront ignorés sauf si échappés. . .
[Link] 6
Expressions régulières PCRE: exemples
Exemples:
new(?!s) sur "Those news seem newer than new"
(?ms)ˆa(.)*z$ sur "abcd\ngfz\na"
regexp pour valider mots de passe ( 8 symboles, chiffre, ponctuation, majuscule) ?
([a-c])z\1\1 équivaut à (?P<lettre>[a-c])z\1\1 et à (?<le>[a-c])z\k<le>\k<le>
Find: (?P<annee>\d{4})-(?P<mois>\d{2})-(?P<jour>\d{2})
Replace: \g<jour>/\g<mois>/\g<annee>
[Link] 7
Expressions régulières: quantificateurs gourmands, paresseux, possessifs
Greedy, lazy/reluctant, possessive quantifiers:
Par défaut, les quantificateurs PCRE sont gloutons: à partir d’une position, autant
d’occurrences que possible, puis backtrack si pas trouvé de solution pour le motif global.
Avec ? le quantificateur devient paresseux: le moins d’occurrences, puis augmente si
pas de solution.
Avec + le quantificateur devient possessif (Java, Python, Perl...): maximum
d’occurrences, sans backtracking même si cela fait échouer.
Exemples:
ba* sur "abaaac"
ba*ac sur "abaaac"
ba+? sur "abaaac"
ba+?c sur "abaaac"
ab{2,}+[a-z] sur "aabbc"
ab{2,}+[a-z] sur "aabbb"
([a-c])*+cz n’a jamais de match.
[Link] 8
Expressions régulières sous UNIX: grep, sed. BRE par défaut, mais ERE avec option -E
egrep = grep -E : dans fichier(s) en entrée, renvoie les lignes où le motif est trouvé.
-i insensible casse
-n affiche numéros de ligne
-R (recursive) tous les fichiers du répertoire
-l n’affiche que le nom des fichiers (donc s’arrête à la 1ère occ. par fichier)
-a cherche dans fichier binaire comme si c’était du texte
-A / -B / -C affiche les lignes autour de l’occ.
--include / --exclude / --exclude-dir précise les fichiers à traiter : utile avec -R.
sed est un outil très complet pour sélectionner ou modifier du texte.
-E ERE au lieu de BRE (sous Mac&GNU), -r (GNU)
-i modifie le fichier d’origine
-e à écrire avant chaque action si il y en a plusieurs (ou -f scriptfile : script passé dans un fichier)
. . . beaucoup d’autres possibilités (options, syntaxe)
sed -e 's/before/after/g' [Link] > [Link]
. . . remplace chaque occ. de before par after.
Exemples:
egrep 'ion$' /usr/dict/words . . . retourne mots se terminant par ion.
grep -rE --color='auto' '\best\b' Desktop/ . . . recherche le mot est dans Desktop.
grep -Ein -B4 --color='auto' 'port' Desktop/[Link]
. . . cherche port (majuscules possibles), affiche les 4 lignes avant, numérotées
find / -type f -exec grep -l 'motif' {} \; (associé à find pour préciser les fichiers)
sed -[Link] 's#([0-9]{4})-([0-9]{2})-([0-9]{2})#\3/\2/\1#g' [Link]
[Link] . . . change format de date sur-place, sauvegarde. 9
Outils de scripts plus riches que sed et grep: syntaxe PCRE
ack: usage plus pratique que grep (voir [Link]
- mêmes regexp que perl
- par défaut: recherche récursive et restreinte aux fichiers de code (pas binaires, .git. . . )
- coloration
ag: similaire à ack (clone) réputé rapide
awk: réputé plus pratique que sed si le fichier a une structure.
perl:
Exemples:
perl -pi -e 's/a/b/g' [Link] similaire à sed -i -e ... †
perl -[Link] -pe 's/(?<annee>\d{4})-\d{2}-\d{2}/$+{annee}/g' [Link]
. . . mais sous perl ou awk on peut utiliser une fonction strftime
perl -ne '/\B\u/ && print' [Link] similaire à grep -e ... †
awk -F',' '{print $2}' [Link] renvoie la deuxième colonne d’un csv
awk -F';' '/ˆ[0-5;]*$/{print $9}' [Link] la 9e col. des lignes satisfaisant la regexp
†
mais syntaxe PCRE
[Link] 10
Expressions régulières: Java
Java:
import [Link].*; //Matcher, Pattern
public class Regexptest
{
public static void main(String[] args)
{
[Link]([Link]("\\w* mops", "with 7 mops")); //false
Pattern p = [Link]("([a-z ]*)\\s*side");
Matcher m = [Link]("from side to");
while ([Link]( )) {
[Link]("Line: " + [Link](0)); //"Line: from side"
[Link]("Value: " + [Link](1)); //"Value: from "
[Link]([Link]() + " " + [Link]()); //0 9
}
[Link]([Link]()); //false: should match entire region
[Link]([Link]("z")); //z to
}
}
Classes non supportées: \l \L \u \U. Conditions pas supportées non plus.
[Link] 11
Expressions régulières : Scala
Scala: utilise la librairie Java.
import [Link]
val motif: Regex = """(\d\d\d\d)-(\d\d)-(\d\d)""".r // .r transforme en regexp
val dates = "historique: 2004-01-20, 1958-09-05, 2010-10-06, 2011-07-15"
val allYears = for (m <- [Link](dates)) yield [Link](1)
// itérateur: [Link]() renvoie successivement "2004" , "1958" , "2010"
val YearsOnly = [Link](dates, m => [Link](1))
// historique: 2004, 1958, 2010, 2011
[Link] 12
Expressions régulières : Python
Python: fonctions match, search, findall, sub.
import re
c = [Link]('(\d\d?) \w+ \d{4}', 'le 16 avril 2017')
print [Link](1) # 16
motif = [Link]('\d\d? \w+ \d{4}')
c = [Link]('le 16 avril 2017')
print [Link]() # '16 avril 2017'
[Link]('([0-9]{4})-([0-9]{2})-([0-9]{2})','\\1/\\2/\\3','2016-04-16')
# '2016/04/16'
[Link](r'a?\\[zb]',r'a\z\b') # ['a\\z', '\\b'] Raw string: r'a\z' == 'a\\z'
[Link]('ab','zabc') is None # matches only from start of string.
[Link]('zab','zabc') is None # matches only whole string.
[Link](r'\W','et tu, Brute') == ['et', 'tu', '', 'Brute']
# [Link](delim,str), like [Link](str2) but for regex
Peut évaluer des expressions définies par des caractères Unicode (par défaut), ou par
des caractères ASCII.
[Link] 13
Expressions régulières: SQL
Oracle : conforme avec POSIX ERE.
UPDATE countries
SET name = REGEXP_REPLACE(name,'(.)','\1 ') WHERE name != France;
-- name Brazil devient: B r a z i l
SELECT first_name, last_name FROM employees
WHERE REGEXP_LIKE (first_name, '^Ste(v|ph)en$')
PostgreSQL : implémente motifs regexp-like avec SIMILAR TO et permet quelques
fonctions regexp POSIX:
SELECT col FROM t WHERE (col similar to '%(b|d)%');
-- retourne "abc", mais pas "aca"
SELECT regexp_replace('foobarbaz', 'b..', 'X', 'g')
-- fooXX
MySQL : la librairie regex de Herbert Spencer (POSIX)
MariaDB : librairie PCRE (anciennes versions: regex)
Microsoft SQL Server : prise en charge partielle avec LIKE (afaik)
DB2 : pas directement pris en charge (afaik) ) UDF.
On peut aussi appeler une librairie regexp à travers des UDF.
[Link] 14
Bibliographie
- [Link]
- [Link]
[Link] 15
Bibliographie
- [Link] (très complet et agréable)
- [Link]
- [Link]
- [Link] (très complet)
- [Link]
les-expressions-regulieres-partie-1-2
- https:
//[Link]/questions/22937618/reference-what-does-this-regex-mean
- [Link] (tester/débuger une regex)
- [Link] (perl one-liners)
À la B.U. (Paris-Sud) :
[Link] includes some book reviews.
[Link] 16