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*)?
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”. |
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
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
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.
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
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>
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>
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).
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
Dans le fichier /etc/services, trouvez les lignes contenant ‘ssh’ puis enlevez les lignes dans lesquelles ssh est suivi d’un ‘
’ (espace).
Comptez le nombre de lignes du fichier /etc/services. Enlever toutes les lignes vides du fichier /etc/services, combien reste-t-il de lignes?