7 - Les expressions régulières

Introduction

Dans Linux, beaucoup de tâches se réalisent à l’aide de manipulation de fichiers texte.

Pour manipuler des fichiers texte, il existe de nombreux outils: cat, sed, grep

À l’aide de grep, on a vu comment filtrer un texte pour conserver uniquement les lignes contenant un texte choisi (ou l’inverse).

Mais comment faire si on souhaite filtrer des chaines de caractères plus complexes comme des adresses courriels, des numéros de téléphone, les commentaires dans du code…

Pour ceci on utilisera les expressions régulières qui permettent de définir du texte ayant n’importe quelle forme.

Exemple, l’URL web:

https?://[a-zA-Z0-9\.-]+\.[a-zA-Z]{2,4}(/\S*)?

Premiers pas

Voici quelques exemples et leur résultat.

Expression Description Exemple Contre-exemple
ab Le ET est implicite entre les caractères. “ab” “a”, “b”, chaine vide
. Un seul caractère “a”, “b”, … “ab”, chaine vide
^ Début de la ligne. ^a: un “a” en début de ligne. Toutes les lignes ne commençant pas par un “a”.
$ Fin de ligne. a$: un “a” en fin de ligne. Toutes les lignes ne finissant pas par un “a”.

Exemples :

Garder les lignes contenant la chaine ssh dans le fichier /etc/services:

$ egrep ssh /etc/services

Garder uniquement les commentaires (lignes commençant par un #) dans le fichier /etc/services:

$ egrep '^#' /etc/services

Garder les lignes se terminant par un “s” dans /etc/services:

$ egrep 's$' /etc/services

Garder les lignes contenant les lettres “a” et “z” séparés par un caractère quelconque:

$ egrep 'a.z' /etc/services

Le OU

On peut aussi vouloir filtrer un texte sur plusieurs possibilités.

Dans les expressions régulières, le OU se représente à l’aide de |.

Par exemple, on souhaite filtrer les lignes contenant ssh ou ftp:

$ egrep 'ssh|ftp' /etc/services

Si, dans /etc/services, on souhaite garder les lignes étant des commentaires ou les lignes se terminant par un “s”:

$ egrep '^#|s$' /etc/services

Les ensembles

Que se passe-t-il si on veut les lignes contenant loucher OU toucher OU doucher OU coucher?

On devra écrire une expression comme:

$ egrep 'loucher|toucher|doucher|coucher' <fichier>

Il est possible de simplifier l’expression grâce aux ensembles, l’expression deviendra:

$ egrep '[ltdc]oucher' <fichier>

On pourrait aussi avoir la négation de cet ensemble, c’est-à-dire tous les mots contenant oucher mais qui ne sont pas loucher, toucher, doucher, coucher:

$ egrep '[^ltdc]oucher' <fichier>

On peut aussi définir des intervalles dans les ensembles.

Ensembles Description
[a-z] Toutes les lettres minuscules
[A-Z] Toutes les lettres majuscules
[0-9] Tous les chiffres

On peut combiner les ensembles:

[a-zA-Z0-9] représente tous les caractères alphanumériques, pas ’ ‘, pas de caractères spéciaux…

ATTENTION: un ensemble entre [] comme [a-zA-Z0-9] représente un seul caractère.

Exemples:

Pour trouver tous les services contenant un ‘f’ et un ‘p’ séparés par une lettre minuscule:

$ egrep 'f[a-z]p' /etc/services

Pour trouver les lignes qui commencent par un chiffre:

$ egrep '^[0-9]' /etc/services

Pour trouver les lignes qui commencent par deux chiffres:

$ egrep '^[0-9][0-9]' /etc/services

Pour trouver toutes les lignes qui ne sont pas des commentaires:

$ egrep '^[^#]' /etc/services

Les quantificateurs

Il peut être nécessaire de définir les nombre de répétitions d’une séquence, pour ceci il existe des quantificateurs.

Quantificateur Signification
? 0 ou 1 fois.
+ 1 ou plusieurs fois
* 0 ou plusieurs fois
{2} 2 fois
{2,4} Entre 2 et 4 fois
{2,} Plus de 2 fois

Ces quantificateurs s’appliquent au caractère qu’ils suivent.

Si on cherche www dans un texte, on peut écrire:

$ egrep 'w{3}' <fichier>

Si on cherche les chaines http ou https:

$ egrep 'https?' <fichier>

N’importe quel caractère un nombre quelconque de fois (cet exemple affiche tout le fichier):

$ egrep '.*' <fichier>

Si on cherche n’importe quelle lettre minuscule entre 3 et 6 fois:

$ egrep '[a-z]{3,6}' <fichier>

L’échappement

Certains caractères ont une signification dans les expressions régulières comme ., +, * ou encore ‘ ’.

Comment faire pour les chercher dans un texte?

On devra les protéger ou encore les échapper.

Le caractère d’échappement est le \.

Ainsi, si je cherche les lignes se terminant par un . :

$ egrep '\.$' <fichier>

Ou les groupes de 3 lettres ayant un ‘ ’ avant et après:

$ egrep '\ [a-zA-Z]{3}\ ' <fichier>

Exercices

  1. Dans le fichier fourni ici, trouvez les adresses courriels. Elles contiennent des lettres majuscules ou minuscules, des chiffres et possiblement un ou plusieurs ‘_’ (tiret bas) et un ou plusieurs ‘.’. Ensuite il y a forcément un ‘@’ puis d’autres caractères (lettres majuscules ou minuscules, chiffres, ‘.’, tiret bas ‘_’) ensuite il y a obligatoirement un ‘.’ puis pour finir, entre 2 et 6 lettre majuscules ou minuscules et possiblement un ‘.’ (.qc.ca).

  2. Toujours dans le fichier fourni, trouvez les numéros de téléphone. Ils peuvent être de deux formes:

  • (xxx)xxx-xxxx

  • +1(xxx)xxx-xxxx

  1. Dans le fichier fourni, trouvez les urls qui peuvent ressembler à (avec possiblement un / à la fin):
  1. Dans le fichier /etc/services, trouvez les lignes contenant ‘ssh’ puis enlevez les lignes dans lesquelles ssh est suivi d’un ‘ ’ (espace).

  2. Comptez le nombre de lignes du fichier /etc/services. Enlever toutes les lignes vides du fichier /etc/services, combien reste-t-il de lignes?