Les expressions régulières

Les expressions régulières sont utilisées par un certain nombre de commandes UNIX.

Les expressions régulières sont composées de caractères ordinaires et de caractères spéciaux qui ont une signification particulière.

Il existe 2 types d'expressions régulières :

  • Les expressions régulières basiques (ERb)
  • Les expressions régulières étendues (ERe)

Les ERb sont utilisées par les commandes suivantes :

  • vi
  • grep
  • expr
  • sed

Les ERe sont utilisées par les commandes suivantes :

  • grep avec l'option -e (egrep)
  • awk

 

Caractères communs aux ERb et ERe

Le tableau suivant liste les caractères spéciaux communs aux ERb et aux ERe

Caractère spécial Signification
^ Début de ligne
$ Fin  de ligne
. (point) Un caractère quelconque
[liste_de_caractères] Un caractère cité dans la liste
[^liste_de_caractères] Un caractère qui n'est pas cité dans la liste
* 0 à n fois le caractère ou regroupement précédent
\<expression Début d'un mot. Caractères pouvant faire partie d'un mot : [A-Za-z0-9_]
expression\> Fin d'un mot
\<expression\> Mot complet
\c Protection du caractère spécial "c"

Exemples :

Les expressions "space" et "tab" représentent les touches [espace] et [tabulation].
La tabulation est représentée par les caractères "\t".

Expression régulière Signification
soleil Chaine contenant "soleil".
Exemple de correspondance :
Aujourd'hui il y a du soleil, mais demain il pleut !
soleil toujours.
Passer ses vacances au soleil.
^soleil Chaine commençant par "soleil".
Exemple de correspondance :
soleil toujours.
soleil$ Chaine se terminant par "soleil".
Exemple de correspondance :
Passer ses vacances au soleil.
^[A-Z][5-9].$ Chaine composée de 3 caractères.
Le premier est une majuscule, le second est un chiffre entre 5 et 9 et le dernier un caractère quelconque.
Exemple de correspondance :
B6z
Z5*
^$ Chaine vide (aucun caractère entre ^ et $)
^[space tab]*$ Chaine contenant entre 0 et n caractères espace ou tabulation
7space[0-79]A* Chaine contenant le chiffre 7, suivi d'un espace, suivi de n'importe quel chiffre sauf 8, suivi de la lettre A 0 à n fois.
Exemple de correspondance :
x7 6
abc7 9Axy
7 1AAAAAAAAAAAAAAAAbfgddghjgdhj
[0-9][^A-Z_]$ Chaine dont l'avant dernier caractère est un chiffre et le dernier n'est ni une lettre majuscule ni un caractère souligné.
Exemple de correspondance :
AZER1a
3*
440008b
\<tout Chaine contenant un mot commençant par "tout".
Exemple de correspondance :
bonjour tout le monde
il faut dire toutefois
Exemple de non correspondance :
partout dans le monde
\<tout\>

Chaine contenant le mot "tout".
Exemple de correspondance :
bonjour tout le monde
Exemple de non correspondance :
partout dans le monde
il faut dire toutefois

[0-9][0-9]\.[0-9] Chaine contenant 2 chiffres suivi du caractère . (point) suivi d'un chiffre.
Exemple de correspondance :
4576.45

Les marqueurs ^ et $ perdent leur signification s'ils ne sont pas placés respectivement en début et en fin de l'expression régulière.

Etiquettes: 

Caractères spécifiques aux ERb

Caractère spécial Signification
\{n\} n fois le caractère précédent
\{n,\} Au moins n fois le caractère précédent
\{n,x\} Entre n et x fois le caractère précédent
\(ERb\) Mémorisation d'une ERb
\1, \2, ... Rappel de mémorisation

Dans les ERB, le caractère "\" donne une signification spéciale aux parenthèses et accolades.

Exemple :

Expression régulière Signification
\-[A-Z]\{2\}\- Chaine contenant un mot de 2 lettres majuscules entouré par des tirets (-)
Exemples de correspondance :
BOUCHES-DU-RHONE
EURE-ET-LOIR
VAL-DE-MARNE

Avec la commande grep (ou autre), le tiret (-) doit être protégé par un antislash (\) pour éviter d'être interprété comme une option.

Caractères spécifiques aux ERe

Caractère spécial Signification
? 0 ou 1 fois le caractère ou regroupement précédent
+ 1 à n fois le caractère ou regroupement précédent
{n} n fois le caractère ou regroupement précédent
{n,} Au moins n fois le caractère ou regroupement précédent
{n,x} Entre n et x fois le caractère ou regroupement précédent
(er1) Regroupement
er1 | er2 | er3 Alternatives

Dans les ERe, les accolades et parenthèses perdent leur signification spéciale si elles sont précédées d'un antislash.

Exemples :

Expression régulière Signification
^[+-]?[0-9]+$

Chaine représentant un nombre entier d'au moins 1 chiffre précédé éventuellement du signe + ou -
Exemples de correspondance :
2
-56
+235
789654

\([a-zA-Z]{3}\) Chaine contenant 3 lettres minuscules et/ou majuscules et entourés de parenthèses.
Exemple de correspondance :
HERBIERS        (Les)   Herbiers
\([-a-zA-Z _]{4,}\) Chaine contenant au moins 4 caractères composées de lettres minuscules et/ou majuscules, de tiret (-), d'espace et de tiret bas (_) et le tout entouré de parenthèses.
Exemples de correspondance :
1er (Ouest)
CASTILLON (CANTON DE LEMBEYE)
2e  (Nord-Ouest)
^41|yotte$ Chaine commençant par "41" ou finissant par "yotte"
Exemples de correspondance :
41      57      57463   3       MOSELLE Moselle
41      88      88160   4       VOSGES  Vosges
06      976     97608   0       MAYOTTE Mayotte
(in|re)+

Chaine composée de 1 à n occurences de "in" ou de "re" (en minuscule)
Exemples de correspondance :
Finistère
Indre-et-Loire
Martinique

 

Exploitation des expressions régulières par les commandes

La commande grep

La commande grep permet l'utilisation d'expressions régulières normalisées par POSIX.

Par défaut, la commande grep utilise les ERb.

Associée à l'option -E, elle utilise les ERe.

Exemples :

Avec le fichier depts2012.txt (téléchargeable sur le site de l'INSEE à cette adresse : http://www.insee.fr/fr/methodes/nomenclatures/cog/telechargement.asp)

$ head depts2012.txt && tail depts2012.txt
REGION  DEP     CHEFLIEU        TNCC    NCC     NCCENR
82      01      01053   5       AIN     Ain
22      02      02408   5       AISNE   Aisne
83      03      03190   5       ALLIER  Allier
93      04      04070   4       ALPES-DE-HAUTE-PROVENCE Alpes-de-Haute-Provence
93      05      05061   4       HAUTES-ALPES    Hautes-Alpes
93      06      06088   4       ALPES-MARITIMES Alpes-Maritimes
82      07      07186   5       ARDECHE Ardèche
21      08      08105   4       ARDENNES        Ardennes
73      09      09122   5       ARIEGE  Ariège
11      91      91228   5       ESSONNE Essonne
11      92      92050   4       HAUTS-DE-SEINE  Hauts-de-Seine
..............
11      93      93008   3       SEINE-SAINT-DENIS       Seine-Saint-Denis
11      94      94028   2       VAL-DE-MARNE    Val-de-Marne
11      95      95500   2       VAL-D'OISE      Val-d'Oise
01      971     97105   3       GUADELOUPE      Guadeloupe
02      972     97209   3       MARTINIQUE      Martinique
03      973     97302   3       GUYANE  Guyane
04      974     97411   0       LA REUNION      La Réunion
06      976     97608   0       MAYOTTE Mayotte
$

Rechercher la chaine "loire-atlantique" sans tenir compte de la casse :

$ cat depts2012.txt | grep -i 'loire-atlantique'
52      44      44109   3       LOIRE-ATLANTIQUE        Loire-Atlantique
$

Rechercher les lignes commançant par 21 :

$ cat depts2012.txt | grep '^21'
21      08      08105   4       ARDENNES        Ardennes
21      10      10387   5       AUBE    Aube
21      51      51108   3       MARNE   Marne
21      52      52121   3       HAUTE-MARNE     Haute-Marne
$

Rechercher les lignes se terminant par "ique" :

$ cat depts2012.txt | grep -i 'ique$'
52      44      44109   3       LOIRE-ATLANTIQUE        Loire-Atlantique
02      972     97209   3       MARTINIQUE      Martinique
$

Rechercher les lignes ayant 2 occurences de la lettre "s" :

$ cat depts2012.txt | grep -i 'ss'
11      91      91228   5       ESSONNE Essonne
$

Idem mais avec une ERb :

$ cat depts2012.txt | grep -i 's\{2\}'
11      91      91228   5       ESSONNE Essonne
$

Idem mais avec une ERe :

$ cat depts2012.txt | grep -iE 's{2}'
11      91      91228   5       ESSONNE Essonne
$

Rechercher les lignes ayant un tiret (-) :

$ cat depts2012.txt | grep '\-'
93      04      04070   4       ALPES-DE-HAUTE-PROVENCE Alpes-de-Haute-Provence
93      05      05061   4       HAUTES-ALPES    Hautes-Alpes
93      06      06088   4       ALPES-MARITIMES Alpes-Maritimes
93      13      13055   4       BOUCHES-DU-RHONE        Bouches-du-Rhone
$

Rechercher les lignes contenant les chaines "loir" ou "tique" (peu importe la casse) :

$ cat depts2012.txt | grep -iE 'loir|tique'
24      28      28085   1       EURE-ET-LOIR    Eure-et-Loir
24      37      37261   1       INDRE-ET-LOIRE  Indre-et-Loire
24      41      41018   0       LOIR-ET-CHER    Loir-et-Cher
82      42      42218   3       LOIRE   Loire
83      43      43157   3       HAUTE-LOIRE     Haute-Loire
52      44      44109   3       LOIRE-ATLANTIQUE        Loire-Atlantique
24      45      45234   2       LOIRET  Loiret
52      49      49007   0       MAINE-ET-LOIRE  Maine-et-Loire
72      64      64445   4       PYRENEES-ATLANTIQUES    Pyrenees-Atlantiques
26      71      71270   0       SAONE-ET-LOIRE  Saone-et-Loire
$

Etiquettes: 

La commande expr

Syntaxe :

expr chaine-de-caracteres : expression-reguliere-basique

La commande expr propose l'opérateur ":" qui permet de mettre en correspondance une chaine de caractères avec une expression régulière.

Fonctionnement de l'opérateur ":" :

  • Le nombre de caractères de chaine-de-caracteres correspondant à l'ERb expression-reguliere-basique est affiché à l'écran.
  • Si chaine-de-caracteres correspond à expression-reguliere, la commande retourne un code vrai ($? = 0). Elle retourne un code faux dans le cas contraire ($? = 1).
  • L'expression régulière est comparée par rapport au début de la variable (le "^" est implicite dans l'ERb).
  • Si une partie de l'expression régulière est mémorisée avec \( \), la commande affiche sur le terminal la portion de la chaine correspondante.

Exemples :

Vérifier que la chaine saisie est un nombre.

$ read nb1
34657
$ read nb2
456G43
$

La variable nb1 contient uniquement des chiffres.

$ expr "$nb1" : '[0-9]*$'                   # Equivaut à '^[0-9]*$'
5
$ echo $?
0
$

La variable nb2 contient une lettre.

$ expr "$nb2" : '[0-9]*$'
0
$ echo $?
1
$

Compter le nombre de caractères contenus dans une variable.

$ chaine="Ceci est une ligne de texte"
$ expr "$chaine" : '.*'
27
$

Afficher la partie de la chaine correspondant à la mémorisation (ici, le chiffre entouré de pipe "|")

$ chaine="un|deux|trois|4|cinq|six|sept"
$ expr "$chaine" : '.*|\([0-9]\{1\}\)'
4
$

Le caractère * recherche toujours la chaine la plus longue. Le "|" le plus à droite.

$ expr "$chaine" : '\(.*\)|'
un|deux|trois|4|cinq|six
$

Solution permettant de s'arrêter au premier "|".

$ expr "$chaine" : '\([^|]*\)|'
un
$

Le script suivant test si la saisie correspond à un nombre (positif ou négatif) et effectue la somme des nombres saisis.

$ nl ./sumnb.sh
     1  #!/bin/bash
     2  somme=0
     3  while :
     4  do
     5          echo -e "Saisir un nombre entier : \c"
     6          if read nombre
     7          then
     8                  if ( expr "$nombre" : '[0-9]*$' || expr "$nombre" : '-[0-9]*$' ) > /dev/null
     9                  then
    10                          somme=`expr $somme + $nombre`
    11                  else
    12                          echo "Saisie incorrecte"
    13                  fi
    14          else
    15                  break
    16          fi
    17  done
    18  echo -e "\nResultat : $somme"
    19  exit 0
$

Exécution du script.

$ ./sumnb.sh
Saisir un nombre entier : 45
Saisir un nombre entier : 69
Saisir un nombre entier : er
Saisie incorrecte
Saisir un nombre entier : 9y
Saisie incorrecte
Saisir un nombre entier : 2
Saisir un nombre entier : -89
Saisir un nombre entier : ^d                                # Saisie clavier ctrl+d
Resultat : 27
$

Etiquettes: