===== Expressions régulières =====
Le but de TD est de faire l'apprentissage de la manipulation des expressions régulières. Cet apprentissage s'illustrera au travers de deux outils ''sed'' et ''grep''.
==== Rappels sur les expressions régulières ====
Début de ligne : ^
Fin de ligne : $
N'importe quel caractère : .
Zéro ou une occurrence : ?
Zéro ou plusieurs occurrences : *
Une ou plusieurs occurrences : +
Exactement 'n' occurrences : {n}
Au moins 'n' occurrences : {n,}
Entre n et m occurrences : {m,n}
'a' ou 'b' ou 'c' : a|b|c
Ensemble de caractères {a, b, c} : [abc]
Ensemble de caractères {a, ..., z } : [a-z]
Caractère n'appartenant pas à l'ensemble : [^...]
Regroupement et capture de caractères. : (...)
Références à des regroupements. : \1, \2, ...
==== Rappel sur SED ====
Il s'agit d'un éditeur ne travaillant pas en mode interactif. Les fichiers édités ne sont pas modifiés : leur contenu est simplement utilisé pour construire un flux sur la sortie standard. A ce titre ''sed'' est un filtre pour le ''bash''.
sed [-n] [-e command_sed] [-f file_com] [ref ...]
... a pour effet de copier le (ou les fichiers) sources ''ref'' sur la sortie standard après application aux lignes complètes du fichier (c'est-à-dire contenant un caractère de fin de ligne) de toutes les commandes contenues dans le fichier ''file_com'' et les différentes commandes introduites en paramètres par un argument ''-e'' (''-e'' est l'option par défaut). Par défaut, le fichier traité est l'entrée standard.
=== Forme générale des commandes ===
[adresse1 [,adresse2]] fonction [argument ...]
Une adresse est :
* soit un nombre décimal qui représente le numéro de ligne (quand il y a plusieurs fichiers, l'éditeur considère qu'il y en a qu'un formé de la concaténation des différents fichiers);
* soit le caractère ''$'' interprété comme l'adresse de la dernière ligne ;
* une expression régulière entre exprimée entre deux ''/''.
Intervalle concerné : ''adresse1'', ''adresse2'' (par défaut, tout le fichier sera traité). On peut imbriquer les commandes afin de les appliquer à une même adresse, on utilise alors ''\{'' et ''\}'' aprés ''adresse''.
=== Le fonctionnement ===
''sed'' maintient un tampon de travail où chaque ligne est successivement chargée et toutes les commandes qui la concernent (''adresse1'', ''adresse2'') lui sont appliquées, après quoi la ligne est écrite sur la sortie standard (sauf si ''-n'' a été donné au chargement, auquel cas seules les commandes explicites d'impression provoqueront une impression). Quand toutes les instructions ont été appliquées, la ligne courante est affichée et la ligne suivante est placée dans le tampon de travail.
=== Les fonctions ===
^ nb adr | commande | actions |
^ [0] | ''# texte'' | commentaire jusque la fin de ligne |
^ [1] | ''a\ texte'' | concaténation du texte avant de lire la ligne suivante |
^ [2] | ''c\ texte'' | suppression de l'espace de travail correspondant à l'intervalle et écriture du ''texte'' sur la sortie. |
^ [2] | ''d'' | suppression de l'espace de travail. Exemple : ''sed /toto/d file'' supprime les lignes contenant ''toto'' dans ''file'' |
^ [2] | ''D'' | suppression de l'espace de travail jusqu'au premier caractère de fin de ligne (précédé du caractère ''\'' qu'il contient) |
^ [1] | ''i\ texte'' | insertion du ''texte'' sur la sortie standard |
^ [2] | ''p'' | écrit l'espace de travail sur la sortie standard. Exemple : ''sed} -n /toto/p file'' n'écrit que les lignes de ''file'' contenant ''toto'' |
^ | q | terminaison |
^ [2] | ''r file'' | écrit le contenu de ''file'' avant de continuer |
^ [2] | ''s/regexpr/ chaine/ind'' | substitution d'un motif à un autre défini au moyen d'expressions régulières. Les indicateurs sont ''g'' : toutes les occurrences, ''p'' : écrit si une substitution a été effectuée, ''w file'' : écriture dans ''file''. Le contenu est concaténé si une substitution a été effectué. |
^ [2] | ''w file'' | écrit l'espace de travail dans ''file''. |
^ [2] | ''y/chaine1/chaine2'' | toutes les occurrences des caractères figurant dans ''chaine1'' sont remplacées par le caractère correspondant (c'est-à-dire en même position) de ''chaine2''. |
^ [2] | ''! commande'' | exécution de la ''commande'' sur les lignes dont l'adresse n'est pas dans l'intervalle. |
^ [2] | ''='' | Donne le numéro de la ligne sélectionnée sur la sortie standard. |
==== Un peu d'entraînement ====
* Que fait la commande suivante ?
sed -n '/^[0-9]\+$/p' fich.txt
* Donner le résultat de la commande suivante pour différentes valeurs de ''motif'' :
echo aabbabbaab | sed $motif
motif='s/[ab]*/x/'
motif='s/a.*b/y/'
motif='s/a.*bb/z/'
motif='s/a\?b/z/g'
motif='s/aab\|ba\|bba/ab/g'
* Donner le résultat des commandes suivantes :
echo "ejkf fed 158e fd" | sed 's/[^0-9]*\([0-9]\+\)[^0-9]*/\1/
echo "ejkf fed 158e fd" | sed 's/.*\([0-9]\+\).*/\1/'
==== HEAD ====
Réécrire la commande ''head'' en utilisant ''sed''.
==== HTML ====
Ecrire un script qui extrait le titre de toutes les pages ''html''.
==== A partir d'un fichier ... ====
On suppose le fichier suivant ''fich.txt'' qui contient :
Marcel:Michu:16:55:09
Ghislaine:Verboten:56:13:29
Raymond:Calbuth:25:67:09
* Ecrire une commande qui transforme les caractéres du fichier ''fich.txt'' en majuscule
* Ecrire une commande qui extrait la première colonne du fichier ''fich.txt''. Le caractère de séparation est '':''.
* Déplacer la colonne de gauche en dernière position.
==== DATE ====
La fonction date renvoie un résultat de la forme suivante :
jeu jan 26 17:26:47 CET 2019
Ecrivez une commande, en utilisant ''date'' et ''sed'', permettant d'obtenir le résultat suivant :
Nous sommes le jeu 26 jan 2019 et il est 17:26:47.
Ecrire la commande ''grep'' permettant de récupérer dans le fichier ''fich.txt'' les lignes contenant des heures valides (format ''hh:mm:ss'').
==== Un peu de GREP ====
Que font les commandes suivantes ? (''[ ]'' contient un espace et une tabulation) :
grep -E -c '^[ ]*$' fich.txt
grep -E -c '^[^ ]+$' fich.txt
grep -E -c '[^ ]' fich.txt
grep -E -n -v '[^ ]+$' fich.txt
==== Lister des fichiers ====
La commande ''ls -l'' produit la sortie suivante
drwxr-xr-x 4 gilles staff 128 22 jan 11:41 dir-1
drwxr-xr-x 2 gilles staff 64 22 jan 14:41 dir-2
-rw-r--r-- 1 gilles staff 0 22 jan 22:39 file-1
-rw-r--r-- 1 gilles staff 0 22 jan 08:18 file-2
-rw-r--r-- 1 gilles staff 0 22 jan 07:03 mon-script-exemple.sh
* Modifiez cette commande afin d'obtenir :
dir-1 modifie a 11:41
dir-2 modifie a 14:41
file-1 modifie a 22:39
file-2 modifie a 08:18
mon-script-exemple.sh modifie a 07:03
==== Liste des extensions ====
$> ls
abc ab.o ab.tar.gz a.c a.o bcabdc.c ccabdc.zip
Ecrivez la commande permettant d'obtenir l'affichage suivant :
.c
.gz
.o
.zip