... l'activité intellectuelle associée avec le développement de logiciels est à coup sûr d'un grand enrichissement.
-- Stowe Boyd
Pour utiliser complètement la puissance de la programmation par script shell, vous devez maîtriser les expressions rationnelles. Certaines commandes et utilitaires habituellement utilisés dans les scripts, tels que grep, expr, sed et awk interprètent et utilisent les ER. À partir de la version 3, Bash possède son propre opérateur de correspondance d'expression rationnelle : =~.
Une expression est une chaîne de caractères. Ces caractères qui ont une interprétation en dehors de leur signification littérale sont appelés des méta caractères. Par exemple, un symbole entre guillemets peut dénoter la parole d'une personne, ditto, ou une méta-signification [94] pour les symboles qui suivent. Les expressions rationnelles sont des ensembles de caractères et/ou méta-caractères qui correspondent ou spécifient des modèles.
Une expression rationnelle contient un élément ou plus parmi les suivants :
Un ensemble de caractères. Ces caractères conservent leur signification littérale. Le type le plus simple d'expression rationnelle consiste en seulement un ensemble de caractères, sans métacaractères.
Une ancre. Elles désignent la position dans la ligne de texte à laquelle doit correspondre l'ER. Par exemple, ^ et $ sont des ancres.
Modificateurs. Ils étendent ou réduisent l'ensemble de texte auquel l'ER doit correspondre. Les modificateurs incluent l'astérisque, les crochets et l'antislash.
Les principales utilisations des expressions rationnelles (ER) sont la recherche de texte ou la manipulation de chaînes. Une ER correspond à un seul caractère ou à un ensemble de caractères (une sous-chaîne ou une chaîne complète).
L'astérisque -- * -- correspond à toute répétition de caractères d'une chaîne ou d'une ER la précédant, incluant zéro caractère.
« 1133* » correspond à 11 + un ou plus de 3 : 113, 1133, 1133333 et ainsi de suite.
Le point -- . -- correspond à un seul caractère, sauf le retour à la ligne. [95]
« 13. » correspond à 13 + au moins un caractère (incluant une espace): 1133, 11333 mais pas 13 (un caractère supplémentaire manquant).
Voir Exemple 16.18, « Résolveur de mots croisés » pour une démonstration de la correspondance par un point (un seul caractère).
La puissance -- ^ -- correspond au début d'une ligne mais, quelque fois, suivant le contexte, inverse la signification d'un ensemble de caractères dans une ER.
Le signe dollar, $, à la fin d'une ER correspond à la fin d'une ligne.
« XXX$ » correspond à XXX à la fin d'une ligne.
« ^$ » correspond à des lignes blanches.
Les crochets -- [...] -- englobent un ensemble de caractères pour réaliser une correspondance dans une seule ER.
« [xyz] » correspond à l'un des caractères x, y ou z.
« [c-n] » correspond à l'un des caractères compris entre c et n.
« [B-Pk-y] » correspond à l'un des caractères compris entre B et P, ou entre k et y.
« [a-z0-9] » correspond à une lettre seule, en minuscules, ou à un chiffre.
« [^b-d] » renvoie à n'importe quel caractère sauf ceux compris entre b et d. Ceci est un exemple de l'inversion de la signification de l' ER qui suit à l'aide de l'opérateur ^ (même rôle que ! mais dans un contexte différent).
Les séquences combinées de caractères entre crochets correspondent à des modèles de mots communs. « [Yy][Ee][Ss] » correspond à yes, Yes, YES, yEs et ainsi de suite. « [0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9] » correspond à tout numéro de sécurité sociale (NdT : du pays d'origine de l'auteur).
L'antislash -- \ -- échappe un caractère spécial, ce qui signifie que le caractère est interprété littéralement (et ne mérite donc plus le qualificatif spécial).
Un « \$ » renvoie la signification littérale de « $ » plutôt que sa signification ER de fin de ligne. De même un « \\ » a la signification littérale de « \ ».
Les signes « inférieur et supérieur » échappés -- \<...\> -- indiquent les limites du mot.
Ces signes doivent être échappés, sinon ils n'ont que leur signification littérale.
« \<le\> » correspond au mot « le » mais pas aux mots « les », « leur », « belle », etc.
bash$ cat fichiertexte This is line 1, of which there is only one instance. This is the only instance of line 2. This is line 3, another line. This is line 4. bash$ grep 'the' fichiertexte This is line 1, of which there is only one instance. This is the only instance of line 2. This is line 3, another line. bash$ grep '\<the\>' fichiertexte This is the only instance of line 2.
ER étendues. Des méta-caractères supplémentaires ajoutés à l'ensemble de caractères. Utilisées dans egrep, awk et Perl.
Le point d'interrogation -- ? -- correspond à aucune ou une instance de la précédente ER. Il est généralement utilisé pour correspondre à des caractères uniques.
Le signe plus -- + -- correspond à un ou plus de la précédente ER. Il joue un rôle similaire à *, mais ne correspond pas à zéro occurrence.
# Les versions GNU de sed et awk peuvent utiliser "+", # mais il a besoin d'être échappé. echo a111b | sed -ne '/a1\+b/p' echo a111b | grep 'a1\+b' echo a111b | gawk '/a1+b/' # Tous sont équivalents. # Merci, S.C.
Les « accolades » échappées -- \{ \} -- indiquent le nombre d'occurrences à filtrer par une précédente ER.
Il est nécessaire d'échapper les accolades car, sinon, elles ont leur signification littérale. Cette usage ne fait techniquement pas partie de l'ensemble des ER de base.
« [0-9]\{5\} » renvoie à exactement cinq entiers (caractères de 0 à 9).
Les accolades ne sont pas disponibles comme ER dans la version « classique » (non conforme à POSIX) de awk. Néanmoins, la version GNU de awk, gawk, dispose de l'option --re-interval qui permet leur utilisation (sans échappement).
bash$ echo 2222 | gawk --re-interval '/2{3}/' 2222
Perl et quelques versions de egrep ne nécessitent pas les accolades échappées.
Les parenthèses -- ( ) -- délimitent des groupes d'ER. Elles sont utiles avec l'opérateur « | » et lors de l'extraction de sous-chaînes en utilisant expr.
L'opérateur d'ER « ou » -- | -- correspond à n'importe lequel d'un ensemble de caractères constituant l'alternative.
bash$ egrep 're(a|e)d' misc.txt People who read seem to be better informed than those who do not. The clarinet produces sound by the vibration of its reed.
Quelques versions de sed, ed et ex supportent les versions échappées des expressions rationnelles étendues décrites ci-dessus, comme le font les outils GNU.
Classes de caractères POSIX. [:class:]
Ceci est une autre façon de spécifier un intervalle de caractères à filtrer.
[:alnum:] correspond aux caractères alphabétiques et numériques. Cette expression équivaut à A-Za-z0-9.
[:alpha:] correspond aux caractères alphabétiques. Cette expression équivaut à A-Za-z.
[:blank:] correspond à une espace ou à une tabulation.
[:cntrl:] correspond aux caractères de contrôle.
[:digit:] correspond aux chiffres (décimaux). Cette expression équivaut à 0-9.
[:graph:] (caractères graphiques affichables). Correspond aux caractères compris entre ASCII 33 - 126. C'est la même chose que [:print:], (cf ci-dessous) mais en excluant le caractère espace.
[:lower:] correspond aux caractères alphabétiques minuscules. Cette expression équivaut à a-z.
[:print:] (caractères imprimables). Correspond aux caractères compris entre ASCII 32 - 126. C'est identique à [:graph:], ci-dessus, mais en ajoutant le caractère espace.
[:space:]> correspond aux blancs (espace et tabulation horizontale).
[:upper:] correspond à tout caractère alphabétique majuscule. Cette expression équivaut à A-Z.
[:xdigit:] correspond aux chiffres hexadécimaux. Cette expression équivaut à 0-9A-Fa-f.
Les classes de caractères POSIX nécessitent généralement d'être protégées ou entre crochets doubles ([[ ]]).
bash$ grep [[:digit:]] fichier.test abc=723
# ... if [[ $arow =~ [[:digit:]] ]] # Entrée numérique ? then # classe de caractères POSIX if [[ $acol =~ [[:alpha:]] ]] # Nombre suivi d'une lettre ? Interdit ! # ... # Extrait du script d'exemple ktour.sh.
Ces classes de caractères pourraient même être utilisées avec le remplacement, jusqu'à un certain point.
bash$ ls -l ?[[:digit:]][[:digit:]]? -rw-rw-r-- 1 bozo bozo 0 Aug 21 14:47 a33b
Les classes de caractères POSIX sont utilisées dans l'Exemple 16.21, « toupper : Transforme un fichier en majuscule. » et l'Exemple 16.22, « lowercase : Change tous les noms de fichier du répertoire courant en minuscule. ».
Sed, awk et Perl, utilisés comme filtres dans des scripts, prennent des ER en arguments lorqu'une transformation, ou une analyse de fichiers ou de flux doit se faire. Voir l'Exemple A.12, « behead: Supprimer les en-têtes des courriers électroniques et des nouvelles » et l'Exemple A.16, « tree: Afficher l'arborescence d'un répertoire » pour des illustrations sur ceci.
La référence sur ce thème complexe est Mastering Regular Expressions de Friedl. Sed & Awk par Dougherty et Robbins donne aussi un traitement très lucide des ER. Voir la Bibliographie pour plus d'informations sur ces livres.
[94]
Une méta-signification est la signification d'un terme ou d'une expression sur un plus haut niveau d'abstraction. Par exemple, la signification litérale d'une expression rationnelle est une expression ordinaire qui se conforme à l'usage accepté. La méta-signification est drastiquement différent. C'est discuté en longueur dans ce chapitre.
[95] Comme sed, awk et grep travaillent ligne par ligne, il n'y aura en général pas de retour à la ligne à chercher. Dans les cas où il existerait un retour à la ligne dans une expression à plusieurs lignes, le point correspondra au retour à la ligne.
#!/bin/bash sed -e 'N;s/.*/[&]/' << EOF # Document en ligne ligne1 ligne2 EOF # SORTIE: # [ligne1 # ligne2] echo awk '{ $0=$1 "\n" $2; if (/ligne.1/) {print}}' << EOF ligne 1 ligne 2 EOF # SORTIE: # ligne # 1 # Merci, S.C. exit 0