Mini-test 10
Expressions regulieres : decrire un motif et l'utiliser avec grep et sed
12 questions ciblees
Cliquez Voir la solution sur chaque slide
Question 1 / 12 choisir un caractere (drag-and-drop)
5 motifs et leur signification :
. est le joker universel. Les crochets [ ]
definissent une classe (un caractere parmi). Le tiret entre 2 caracteres
dans une classe = intervalle. ^ en debut de classe = negation.
Sans crochets ni meta-caracteres = chaine litterale.
| Motif | Match | Exemples |
|---|---|---|
. | N'importe quel caractere unique | a, Z, 5, !, espace... |
[0-9] | Un chiffre | 0, 1, 2, ..., 9 |
[^0-9] | Tout SAUF un chiffre | a, Z, !, espace... (mais pas 0-9) |
[a-z] | Une lettre minuscule | a, b, c, ..., z |
allo | La chaine litterale "allo" | allo (et juste allo, dans cet ordre) |
Note importante : sans meta-caracteres (ni ., ni [], ni +...), une regex est juste une chaine litterale. allo matche le mot allo. 418 matche les 3 chiffres 4, 1, 8 dans cet ordre.
Autres classes utiles :
[A-Z] une lettre majuscule [A-Za-z] une lettre (peu importe la casse) [a-zA-Z0-9] alphanumerique [0-9a-fA-F] un chiffre hexa
Question 2 / 12 multiplicateurs (drag-and-drop)
5 multiplicateurs et leur signification :
? facultatif,
+ au moins une, * zero ou plus.
Pour des comptes precis : {N} exact, {N,M} intervalle.
| Symbole | Signification |
|---|---|
? | 0 ou 1 fois (facultatif) |
+ | 1 ou plusieurs (au moins une) |
* | 0 ou plusieurs (eventuellement aucune) |
{3} | Exactement 3 fois |
{3,5} | Entre 3 et 5 fois |
Equivalences :
{0,1} equivalent a ?
{1,} equivalent a +
{0,} equivalent a *
{,5} au maximum 5 fois
{3,} au moins 3 fois
Exemples concrets :
colou?r matche "color" ET "colour"
hel+o matche "helo", "hello", "helllo"...
[0-9]{4} exactement 4 chiffres (annee)
[a-z]{3,8} mot de 3 a 8 lettres minuscules
Question 3 / 12 ancres + echappement (drag-and-drop)
5 contextes possibles pour ^, $ et - :
^ et $ ont 2 sens : ancre quand seuls,
negation quand au DEBUT d'une classe [ ].
Pour rendre un meta-caractere litteral : soit l'echapper avec
\, soit le mettre a un endroit ou il n'a pas de sens
special (ex. - en fin de classe).
| Forme | Role |
|---|---|
^abc | Ancre debut de ligne : abc doit etre au debut |
abc$ | Ancre fin de ligne : abc doit etre a la fin |
[^abc] | Negation dans classe : un caractere SAUF a, b, c |
\$ | Echappement : le caractere $ litteral |
[abc-] | Tiret en fin de classe : litteral (pas un intervalle) |
Memo important : 2 sens pour ^
^abc : ancre debut de ligne (en DEHORS de crochets)[^abc] : negation (en DEBUT de crochets)Memo important : le tiret - dans une classe
[a-z] : intervalle (tiret au MILIEU)[abc-] : litteral (tiret a la FIN ou au debut)[\-] : echappe (litteral peu importe la position)Question 4 / 12 intervalle vs liste de caracteres
[ ], le tiret
change tout. Comparons deux motifs qui se ressemblent visuellement.
[ ] definissent une liste de caracteres possibles,
un seul est choisi. Le tiret entre 2 caracteres = intervalle.
Sans tiret = liste litterale. Pour matcher une chaine de plusieurs
caracteres dans l'ordre, on les met cote a cote SANS crochets.
[0-9] = un seul caractere parmi
l'intervalle 0 a 9 (donc 0, 1, 2, ..., 9). Le tiret
signifie "intervalle".
[009] = un seul caractere parmi
la liste {0, 0, 9}. Le 0 est en double mais c'est
comme si on avait [09]. Donc : 0 ou 9.
009 (sans crochets) = la chaine
litterale 009 (trois caracteres dans cet ordre).
| Motif | Match ? | Exemples qui matchent |
|---|---|---|
[0-9] | 1 chiffre | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 |
[009] | 1 chiffre | 0 ou 9 (le 0 en double sert a rien) |
009 | 3 caracteres | 009 (et seulement 009) |
[0-9]{3} | 3 chiffres | 000, 123, 456, 999... |
Piege classique : [A-z] n'est PAS [A-Za-z] !
Entre Z et a dans la table ASCII, il y a des caracteres comme
[ \ ] ^ _ `.
Toujours preferer [A-Za-z].
Question 5 / 12 concatenation et alternation (QCM)
[ ] ni |, on a une chaine litterale.
Le | entre 2 mots cree des alternatives (mots entiers).
Les [ ] ne contiennent que des caracteres (un seul est choisi).
(...)+ repete tout le groupe.
| Regex | Match | Exemples qui matchent |
|---|---|---|
chatouille | Chaine litterale | chatouille (et juste chatouille) |
chat|ouille | Alternation : un mot OU l'autre | chat ou ouille (pas les deux) |
[chatouille] | Classe : UN SEUL caractere | c, h, a, t, o, u, i, l, e (juste 1 lettre) |
(chat|ouille)+ | Groupe + repetition | chat, ouille, chatchat, chatouille, ouillechat, chatouilleouillechat... |
Memo crucial :
| entre = alternation (un seul des deux mots)[ ] = classe (un seul caractere parmi)( ) regroupe pour appliquer un quantificateur ou pour faire une captureQuestion 6 / 12 indicatifs au choix (drag-and-drop)
5 ecritures, 5 comportements differents :
[ ] = ensemble de caracteres,
un seul est choisi. Pipe | = alternative entre des
chaines, mais SEULEMENT en dehors des crochets. Dans
une classe, le | est litteral. Le ( )
regroupe l'alternation.
| Ecriture | Match reellement |
|---|---|
(418|514|819) | 418 OU 514 OU 819 (alternation groupee, capturable) |
418|514|819 | 418 OU 514 OU 819 (alternation sans groupe) |
[418514819] | UN seul chiffre parmi {1, 4, 5, 8, 9} |
[418|514|819] | UN seul caractere parmi {1, 4, 5, 8, 9, |} |
418 | La chaine exacte 418 (3 chiffres dans cet ordre) |
En pratique on prefere :
# Pour chainer avec le reste du numero
(418|514|819)-[0-9]{3}-[0-9]{4}
Question 7 / 12 cas pratique : telephone (1/2)
555-1234 puis
418-555-1234. Construisons par etapes, du plus simple au
plus complet. (Un indicatif au choix viendra a la page suivante.)
[0-9]{N} = exactement N chiffres. Equivalent : repeter
[0-9][0-9][0-9]. Pour rendre un fragment facultatif :
l'entourer de parentheses et ajouter ? :
(fragment)?. Le tiret hors classe est un caractere litteral.
# a) Sans indicatif (3 chiffres - 4 chiffres)
[0-9]{3}-[0-9]{4}
# Equivalent avec repetition manuelle
[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]
# b) Avec indicatif obligatoire (n'importe quel)
[0-9]{3}-[0-9]{3}-[0-9]{4}
# c) Indicatif fixe 418 (litteral)
418-[0-9]{3}-[0-9]{4}
# d) Indicatif 418 facultatif (groupe + ?)
(418-)?[0-9]{3}-[0-9]{4}
Notes :
{N} et [chiffre][chiffre]... sont
equivalents. Le premier est plus compact, le second est plus lisible
quand on apprend.?. Sans parentheses, le ?
ne s'applique qu'au caractere precedent.(418-)?[0-9]... matche 418-555-1234
ET 555-1234.La page suivante (Q8) generalise au cas ou l'indicatif peut etre l'un de plusieurs (418, 514, 819) avec ou sans parentheses.
Question 8 / 12 cas pratique : telephone (2/2)
(418)-555-1234 ou
418-555-1234.
(418)-555-1234 OU 418-555-1234. Methode 1 : rendre chaque parenthese ( et ) facultative independamment :(418|514|819) dans un groupe.
Pour rendre tout l'indicatif facultatif : entourer d'un groupe
supplementaire avec ? : ((418|514|819)-)?.
Pour les parentheses litterales ( et ) :
les echapper avec \, et chacune devient facultative avec
? : \(? et \)?.
# a) Au choix obligatoire
(418|514|819)-[0-9]{3}-[0-9]{4}
# b) Au choix facultatif
((418|514|819)-)?[0-9]{3}-[0-9]{4}
# c) Methode 1 : chaque parenthese facultative independamment
\(?(418|514|819)\)?-[0-9]{3}-[0-9]{4}
Caracteristique de la methode 1 : les deux parentheses
sont facultatives independamment l'une de l'autre. C'est plus court
a ecrire, mais ca accepte aussi des cas asymetriques comme
(418-555-1234 (parenthese ouvrante seule) ou
418)-555-1234 (fermante seule). Si on veut empecher
l'asymetrie, il faut une alternative explicite :
c'est l'objet de la question suivante (Q9).
Pour pratiquer les regex sur des exemples reels : regex101.com.
Question 9 / 12 parentheses : alternative explicite
(418-555-1234 (ouvrante seule). Pour
forcer la symetrie (les 2 parentheses ensemble ou
aucune), on utilise une alternative explicite.
Donnez la regex qui matche (418)-555-1234 ou 418-555-1234 mais refuse (418-555-1234 et 418)-555-1234 :
(motif_avec_parens|motif_sans_parens). Chacun des
2 motifs decrit l'indicatif complet (avec ses 2 parentheses, ou aucune).
On echappe ( et ) pour le litteral : \( et \).
# Methode 2 : alternative explicite des deux formes complete
(\((418|514|819)\)|(418|514|819))-[0-9]{3}-[0-9]{4}
Decryptage :
\((418|514|819)\) : indicatif avec les 2 parentheses(418|514|819) : indicatif sans parentheses(... | ...) : un OU l'autre, mais pas un melangeComparaison avec methode 1 (Q8c) :
| Entree | Methode 1 (parens facultatives) | Methode 2 (alternative explicite) |
|---|---|---|
(418)-555-1234 | OK | OK |
418-555-1234 | OK | OK |
(418-555-1234 | accepte (asymetrique) | refuse |
418)-555-1234 | accepte (asymetrique) | refuse |
Version "parfaite" avec ancres :
^(\((418|514|819)\)|(418|514|819))-[0-9]{3}-[0-9]{4}$
La methode 2 est plus stricte et plus correcte en production. La methode 1 est plus courte mais accepte des bizarreries que la methode 2 refuse.
Question 10 / 12 grep -E
/var/log/auth.log contient des lignes de
connexion. On cherche.
grep de base utilise BRE (basique). -E active
ERE (etendue) avec |, +, ? sans
echappement. -o = output only matching part.
NAME
grep, egrep - print lines matching a pattern
SYNOPSIS
grep [OPTION...] PATTERN [FILE...]
DESCRIPTION
grep searches for PATTERN in each FILE.
OPTIONS
Pattern Selection and Interpretation:
-E, --extended-regexp
Interpret PATTERN as an extended regular expression
(ERE) - permits |, +, ?, ( ), {N,M} without backslash.
-F, --fixed-strings
Interpret PATTERN as fixed strings, not as a regex.
-i, --ignore-case
Ignore case distinctions in pattern and input files.
General Output Control:
-c, --count
Suppress normal output; print a count of matching lines.
-l, --files-with-matches
Suppress normal output; print only the name of each
input file from which output would normally be printed.
-o, --only-matching
Print only the matched (non-empty) parts of a matching
line, with each such part on a separate output line.
-v, --invert-match
Invert the sense of matching, to select non-matching lines.
-n, --line-number
Prefix each line of output with the 1-based line number.
Context Line Control:
-r, --recursive
Read all files under each directory, recursively.
# a) Recherche simple (motif fixe) grep "Failed password" /var/log/auth.log # b) Alternation : -E pour ERE, le | sans backslash grep -E "Failed|Invalid" /var/log/auth.log # c) Afficher seulement les matches (utile avec une regex precise) grep -oE "Failed [a-z]+" /var/log/auth.log
Options frequentes de grep :
-E = regex etendue (ERE) : |, +, ?, {} sans backslash-i = insensible a la casse-v = inverse (lignes qui NE matchent PAS)-n = numero de ligne-c = compte les lignes (au lieu de les afficher)-r = recursif dans un repertoire-l = liste seulement les noms de fichiersBRE vs ERE : En BRE (sans -E), + et ? doivent etre echappes \+ \?. Avec -E, ils gardent leur sens regex direct.
Question 11 / 12 sed s/.../.../
"ERROR" par "WARN" dans app.log (afficher le resultat, sans modifier le fichier) :# (commentaires) dans config.conf :sed 's/MOTIF/REMPLACEMENT/FLAGS' fichier.
Flag g = global (toutes les occurrences sur la ligne).
-i = in-place. Pour supprimer : /motif/d.
NAME
sed - stream editor for filtering and transforming text
SYNOPSIS
sed [OPTION...] 'script' [INPUT_FILE...]
DESCRIPTION
sed reads FILE, applies the script, and writes the result.
OPTIONS
-i, --in-place
edit files in place (sans afficher la sortie)
-n, --quiet
supprime l'affichage automatique (utile avec /pattern/p)
-e SCRIPT, --expression=SCRIPT
ajoute SCRIPT aux commandes a executer
-E, --regexp-extended
use extended regular expressions (comme grep -E)
COMMANDES DU SCRIPT (langage sed)
s/REGEX/REPLACEMENT/[FLAGS]
substitute. Flags : g (global, toutes les
occurrences), i (insensitive), p (print)
/REGEX/d
delete les lignes qui matchent REGEX
/REGEX/p
print les lignes qui matchent (avec -n)
Nd
supprime la ligne N
N,Md
supprime les lignes N a M
y/abc/xyz/
transliteration (a->x, b->y, c->z)
EXEMPLES
# Substitution simple
echo "hello" | sed 's/hello/bonjour/'
# In-place avec backup .bak
sed -i.bak 's/foo/bar/g' fichier.txt
# Supprime les lignes vides
sed '/^$/d' fichier.txt
# Affiche les lignes 5 a 10 seulement
sed -n '5,10p' fichier.txt
# Backreferences : inverse "Nom Prenom" en "Prenom Nom"
sed -E 's/^([A-Z][a-z]+) ([A-Z][a-z]+)$/\2 \1/' fichier
# a) Substitution sans modifier le fichier sed 's/ERROR/WARN/g' app.log # b) Modifier le fichier directement (in-place) sed -i 's/ERROR/WARN/g' app.log # c) Supprimer les lignes commencant par # sed '/^#/d' config.conf
Decryptage de la substitution :
sed 's/MOTIF/REMPLACEMENT/FLAGS' fichier
^ ^ ^
| | flags : g (global), i (case-insensitive)
| le remplacement
le motif (regex)
Autres operations sed :
sed -n '/motif/p' : afficher seulement les lignes qui matchentsed '5d' : supprimer la ligne 5sed '1,10d' : supprimer les lignes 1 a 10sed 's|ancien|nouveau|g' : delimiter avec | si / dans le motifBackreferences : dans le remplacement, \1 = premier groupe capture.
# Inverser nom prenom dans un fichier "Prenom Nom" sed -E 's/^([A-Z][a-z]+) ([A-Z][a-z]+)$/\2 \1/' fichier.txt
Question 12 / 12 cas pratique : log Apache
/var/log/apache2/access.log contient des lignes
comme :
grep -oE "regex".
Une IP = 4 groupes de 1 a 3 chiffres separes par des points litteraux.
Attention : . est le joker, il faut l'echapper \..
Pour compter et trier : | sort | uniq -c | sort -rn | head -5.
# a) Extraire toutes les IPs (note les \. pour le point litteral)
grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" /var/log/apache2/access.log
# Plus precis (1 a 3 chiffres par groupe)
grep -oE "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" /var/log/apache2/access.log
# b) Top 5 des IPs les plus frequentes
grep -oE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" /var/log/apache2/access.log \
| sort | uniq -c | sort -rn | head -5
Decryptage de la chaine de commandes :
grep -oE : ne montre que les IPs (pas les lignes)sort : trie pour grouper les IPs identiquesuniq -c : compte les doublons (besoin que ce soit deja trie)sort -rn : tri inverse numerique (de la plus frequente)head -5 : les 5 premieresSortie attendue :
12 192.168.1.42
8 10.0.0.5
5 203.0.113.7
3 198.51.100.99
2 192.168.1.50
Variante plus stricte (vraie IP, octets <= 255) :
# Regex precise pour octets 0-255 (complexe)
grep -oE "(25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})\.(25[0-5]|2[0-4][0-9]|[01]?[0-9]{1,2})" log
# En pratique [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+ suffit dans 99% des cas
Bilan
Pour tester : regex101.com ou regexr.com
R pour recommencer.