Vous êtes sur la page 1sur 25

UNIC J1 - Tutoriel

Copyright
Copyright c Jules Aubert <jules.aubert@ext.devinci.fr>

1
Table des matières

1 Lecture 4
1.1 Qu’est-ce que le shell ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Historique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3 Variation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2 Shell script 5
2.1 Qu’est-ce qu’un script shell ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Entrée / Sortie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2.1 Entrées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2.2 Sorties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.3 Séquence de commandes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3.1 Calcul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.4 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.4.1 Variables communes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.5 Builtins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.6 Structures de contrôle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.6.1 if then else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.6.2 Boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.6.3 switch case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.6.4 Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.7 Exercise : salutation.sh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.8 Exercise : count_files.sh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.9 Fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.10 Globbing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.11 Quoting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.11.1 Double quotes (") . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.11.2 Simple quotes (’) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.11.3 Back-quotes (‘) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

3 Shell script avancé 11


3.1 Redirections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.2 Sous-shells, source et exec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.2.1 Sub-shells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.2.2 Source . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.2.3 Exec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.3 I/O avancé . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

4 Divers (vive le vent, vive le vent...) 13


4.1 Commandes utiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.2 Liens utiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.3 Références . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

5 Expressions régulières 14
5.1 Regex basiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
5.1.1 Le point . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
5.1.2 Début ˆ et fin $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
5.1.3 Alternative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.1.4 Liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.1.5 Intervalle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2
5.1.6 Classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.1.7 Répétition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
5.1.8 Groupement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
5.1.9 Rétro référence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
5.2 Regex étendues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

6 Grep 18
6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
6.1.1 Percée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

7 Sed 19
7.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
7.2 Méchanique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
7.3 Commandes simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
7.3.1 La commande de substitution : s . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
7.3.2 La commande de suppression : d . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
7.3.3 La commande de remplacement : y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
7.3.4 La commande d’affichage : p, l and - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
7.4 Adresses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
7.4.1 Commandes de blocs : ’{}’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
7.4.2 Bloc de remplacement : ’c’ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
7.5 Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
7.6 Commandes avancées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

8 Exercises 23
8.1 Mise en route . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
8.2 squeeze.sh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
8.3 get_line.sh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
8.4 log.sh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
8.5 sum.sh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
8.6 Spell checker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
8.7 Sed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
8.7.1 L’espace fini . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
8.7.2 Grep . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
8.7.3 Head . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
8.7.4 Head | Tail . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
8.8 Compter en binaire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

3
Chapitre 1

Lecture

1.1 Qu’est-ce que le shell ?


Pour utiliser un ordinateur, vous utilisez un système d’exploitation. Le noyau d’un tel système est son kernel. ce noyau est
une entité chargée de gérer les demandes des utilisateurs leur permettant d’accéder aux ressources matérielles et aux
services fournis par votre système. Cependant, le noyau n’est pas suffisant pour utiliser un ordinateur. Il faut ajouter un
programme offrant à l’utilisateur une interface simple lui permettant de transmettre ses requêtes au noyau système. Avec
ces commandes adressées au noyau, l’utilisateur peut, par exemple, voir la liste des fichiers sur son disque dur, démarrer des
applications, etc. Ce programme est appelé shell.

Les systèmes d’exploitation de la famille UNIX utilisent souvent une architecture en couches. Le mot anglais shell a été
choisi car il s’agit d’une interface permettant l’accès aux services du noyau. C’est une sorte de coquille autour du noyau.

1.2 Historique
L’histoire du shell sous sa forme actuelle est étroitement liée à celle d’UNIX. Le début du shell était un programme plutôt
rudimentaire : le Bourne Shell (du nom de son créateur : Stephen Bourne) C’est un interpréteur en ligne de commande. Son
originalité était d’enchaîner les sorties des commandes aux entrées des autres en utilisant des pipes.

Aujourd’hui, le Bourne Shell classique est obsolète, et les développements comme le Bash se sont propagés dans les
systèmes UNIX. Cependant, le Bourne Shell a été standardisé par des spécifications tel que SUS (Single UNIX
specification) et on trouve toujours un équivalent dans les systèmes UNIX modernes.

Le langage (de programmation) utilisé par les différents shells ne sont pas tous compatibles. Donc si tu veux écrire des des
scripts shells portables sur tous les systèmes UNIX, il est recommandé d’utilisé la syntaxe du Bourne shell standardisée et
seulement les commandes de bases du monde UNIX.

1.3 Variation
Le Bourne shell et le shell historique des systèmes UNIX et hérite d’idées initiées par Multics (fin des années 1960s). Le C
shell (Csh) est le shell traditionnel des systèmes BSD (Berkeley Software Distribution). Le Csh utilise une syntaxe similaire
au C et innove avec le Jobs Controls ; cette fonctionnalité sera reprises par le Bourne shell et ses descendants.

En 1988 apparaît Ksh, inspiré par les deux shells précédents (la syntaxe du Bourne shell et les Jobs Controls de Csh). Bash
(écrit en 1987) est le shell basique utilisé par une majorité de systèmes UNIX (Linux, MacOSX, Solaris, etc.). Il reprend les
fonctionnalités de ses prédécesseurs et dépend du projet GNU.

Zsh est un shell plus récent, qui date de 1990 et est inspiré des shells précédents. Il apporte de nouvelles fonctionnalités
telles que la complétion de commandes améliorée, plus d’options et d’arguments, un historique partagé, la correction
d’erreurs typographiques...

TCsh est le shell des systèmes BSD, c’est une amélioration de Csh.

4
Chapitre 2

Shell script

2.1 Qu’est-ce qu’un script shell ?


Tu as déjà utilisé ton shell en entrant des commandes manuellement. Parfois, les traitements que vous devrez effectuer
seront complexes et nécessiteront plusieurs commandes Si on vous demande à plusieurs reprises de refaire la même
opération, il deviendra rapidement fastidieux de retaper manuellement les commandes à chaque fois.

Pour résoudre ces problèmes, il existe une pratique répandue dans le monde UNIX : les shell scripts. Un script shell n’est
ni plus ni moins qu’un fichier dans lequel vous écrivez toutes les commandes nécessaires pour effectuer votre traitement.
Par la suite, ce fichier peut être lu par votre shell qui exécutera les commandes les unes après les autres. On peut donc
considérer un script shell comme un programme interprété.

Nous devons toujours spécifier quel programme sera chargé pour interpréter ton fichier. Sous un système UNIX, nous
utilisons un shebang 1 pour cela. Il se compose des caractères "# !" suivi du chemin absolu de l’interpréteur de commande
"/bin/sh". Le chemin de l’interpréteur peut être suivi par des options pour cela.

Le corps du script shell est une séquence de commandes internes ou externes au shell. Il finit par renvoyer une valeur de
retour, traditionnellement 0 en cas de succès et une autre valeur en cas d’échec.

Pour démarrer votre script shell, deux possibilités existent :


— sh path/to/myscript.sh : le shebang sera ignoré et l’interpréteur sera sh ;
— ./myscript.sh : dans ce cas, le script doit avoir des droits d’exécutions

2.2 Entrée / Sortie


Il y a plusieurs moyens de communiquer avec un script shell.

2.2.1 Entrées
— La ligne de commande : c’est le moyen le plus pratique pour configurer un script. L’inconvénient de ce système
est qu’il nécessite une analyse complète de la ligne de commande pour vérifier la validité des arguments au départ,
sans nécessairement l’ordre de ceux-ci. C’est assez fastidieux pour l’auteur du script.
— L’entrée standard (correspondant au fd 2 0.) : en temps normal, le clavier. C’est un moyen intuitif de
communiquer entre l’utilisateur et le script, mais il n’est pas largement utilisé car un script shell n’a généralement
aucune interaction avec un humain vu qu’il est conçu à l’origine pour automatiser l’exécution des commandes.
— Les fichiers : l’utilisation de fichiers de configuration pour un script shell est facile et recommandée pour un script
qui s’exécutera automatiquement.

2.2.2 Sorties
— La valeur de retour : un programme sur UNIX retourne une valeur. Cette valeur, entre 0 et 255, est utilisé pour
facilement tester s’il s’est arrêté normalement ou avec une erreur différent de 0. De cette façon, si le code a bien été
1. shebang : de la contraction imprécise de sharp et hash bang
2. Sur UNIX, les fichiers ouverts sont identifiés par des nombres, appelés des descripteurs de fichiers (file descriptors (fd)). L’entrée standard
est numéroté 0, la sortie standard est 1 et la sortie d‘erreur est 2

5
pensé, il est facile et rapide d’identifier une erreur. La valeur de retour est enregistré dans une variable spéciale du
shell.
— La sortie standard (correspondant au fd 1) : habituellement l’écran. Il permet d’afficher des informations à
l’utilisateur. Il peut être redirigé vers un fichier pour une analyse ultérieure, ou redirigé vers un autre programme qui
l’utilisera comme entrée.
— La sortie d’erreur (correspondant au fd 2) : habituellement l’écran. C’est le deuxième canal de sortie, le premier
étant plutôt dédié aux sorties normales. Stderr, comme son nom l’indique, est privilégié lorsqu’il s’agit d’émettre un
message d’erreur ou des informations système.
— Les fichiers : ils peuvent servir de moyen de stockage pour le résultat.

2.3 Séquence de commandes


Le shell a plusieurs opérateurs pour contrôler le chaînage de la commande :
— CMD1 ; CMD2 : exécute CMD2 une fois que CMD1 a terminé son exécution
— CMD1 && CMD2 : exécute CMD2 seulement si CMD1 réussi
— CMD1 || CMD2 : exécute CMD2 seulement si CMD1 échoue
— CMD1 | CMD2 : exécute CMD1 et redirige sont stdout au stdin de CMD2
— CMD1 & CMD2 : exécute CMD1 en arrière-plan et CM2 au premier-plan
1 $ true && echo " it ␣ works "
2 it works
3 $ false && echo " it ␣ works "
4 $ cat file . txt | grep toto
5 toto eats bananas
6 toto likes bananas
7 $
8 $ sleep 3 & echo ’I ␣ am ␣ here ’
9 [1] 423 I am here
10 $
11 # 3 seconds later :
12 $ [1]+ Done sleep 3

2.3.1 Calcul
Le shell a un évaluateur d’expressions arithmétiques, $((exp)) où exp est une expression arithmétique qui accepte les
opérations conventionnelels : addition, soustraction, multiplication, division, modulo. Ces opérations peuvent être utilisées
avec des nombres relatifs mais pas décimaux en bash (ça dépend de votre shell).
1 $ x =3
2 $ y =6
3 $ echo $ (( x + (4 - y ) % 3) )
4 1
5 $ echo $ (( $x + (4 - $y ) % 3) )
6 1

2.4 Variables
Les variables shell sont des chaînes de caractères nommées dont le contenu peut changer pendant l’exécution. On instantie
une variable de cette façon : var=valeur.

Avertissement : il n’y a pas d’espace de chaque côté du signe ’=’. L’identifiant doit commencer par un caractère
alphabétique majuscule ou minuscule ou un underscore ’_’ suivi de 0 ou plus caractères alphanumériques, ou un underscore.

On accède au contenu de la variable en utilisant son nom préfixé par le symbole ’$’ : $var. Il est aussi possible d’utiliser la
forme suivante pour éviter une confusion : ${var}.

Le shell a des variables spéciales : ce sont des variables qui contiennent des informations sur le processus en cours, la valeur
de retour du dernier programme, le nombre d’arguments d’un script ou d’une fonction, etc.

$? Valeur de retour de la dernière commande exécutée


$# Nombre d’argument du script ou de la fonction
$0 Nom du script ou de la fonction
$n Valeur du nth paramètre du script ou de la fonction
$@ Liste tous les arguments sans substitution
$* Liste tous les arguments, en un seul mot
$$ PID du shell courant
$! PID de la dernière tâche lancée en arrière-plan

6
Dans le shell, il y a deux types de variables :
— les variables internes au shell, qui ne peuvent être utilisées dans le shell courant et être créées comme expliqué
précédemment
— les variables d’environnement, qui sont utilisées dans le shell actuel ainsi que dans des éventuels sous-shells. En
réalité, elles peuvent être utilisées par n’importe quel programme lancé depuis le shell où tu as défini ces dîtes
variables
Avertissement : Les sous-shells n’ont pas d’accès direct au variables d’environnement du shell parent. Il possèdent une
copie. Ainsi, les sous-shells ne peuvent pas changer les variables d’environnement du shell d’origine. Ils peuvent éditer leurs
copies, mais le changement ne sera visible que dans le shell où les changements on eu lieu. Pour créer des variables
d’environnement, nous procédons de la même façon que pour créer des variables internes au shell. Toutefois, il faudra
utiliser la commande export pour demander au shell d’exporter cette variable dans l’environnement

2.4.1 Variables communes


Dans les systèmes UNIX, beaucoup de variables d’environnement ont une signification spéciale et t’autorise à configurer ou
d’obtenir des informations sur ton système. Ton shell vous fournit également des variables vous permettant d’interagir avec
lui. Voici une liste partielle de ces variables et de leurs significations :

$PATH Liste des répertoires où le shell est autorisé à rechercher un exécutable si


son chemin absolu ou relatif n’est pas spécifié.
C’est à travers ce mécanisme que vous pouvez simplement taper ls plutôt que /bin/ls
$LD_LIBRARY_PATH Liste des répertoires où les chargeurs de bibliothèques ont le droit de chercher
les bibliothèques dynamiques nécessaires pour le programme
$USER Nom de l’utilisateur actuel
$HOSTTYPE Architecture système
$HOSTNAME Nom de la machine
$PS1 Configuration du prompt utilisateur
$SECONDS Temps en secondes depuis l’ouverture du shell ou la dernière réinitialisation à 0
$OLDPWD Chemin vers le répertoire précédent visité
$EDITOR Éditeur préféré de l’utilisateur
$TERM Type de terminal actuel
$SHELL Shell utilisateur
$SHLVL SHell LeVeL : nombre de shells imbriqués au-dessus du shell actuel
Tu peux toujours voir toutes les variables d’environnement dans votre shell, en utilisant la commande env.

2.5 Builtins
La plupart des commandes que tu utilises sont des programmes distincts. C’est le cas, par exemple, de ls ou cp. Les builtins
sont des commandes intégrées au shell et exécutées par le shell lui-même. Ce sont généralement des fonctionnalités de bas
niveau du shell telles que cd ou des fonctions de gestion de variables d’environnement comme export. Pour vérifier si une
commande est un builtin ou non, nous pouvons utiliser le builtin builtin. Voici une liste partielle des builtins les plus
utilisés, la liste des builtins disponibles pour le CLI (Command Line Interface) est donnée dans le manuel de votre shell.

exit Quittez le shell actuel avec l’argument donné comme valeur de retour.
Si la valeur est omise, 0 est renvoyé par défaut
cd Changez de répertoire et déplacez-vous dans le dossier spécifié par l’argument
echo Affiche les arguments sur stdout (sortie standard))
source Exécuter un script shell dans le shell en cours
shift Supprime les N premiers arguments de la ligne de commande (par défaut 1)
eval Construire une commande à partir des arguments donnés

2.6 Structures de contrôle


Le shell te laisse utiliser des structures de contrôle comme if ou les boucles. La condition de contrôle de ces commandes est
la valeur de retour de la condition de contrôle : 0 est vrai, toute autre valeur est fausse.

2.6.1 if then else


Les mot-clés if, then, else sont utilisés pour tester la validité d’une condition et brancher le script de la partie intéressante.
Un structure if then else termine toujours avec un fi. Une condition est dîte validée si la valeur de retour du dernier
programme exécuté est nul.

7
1 if CONDITION ; then
2 COMMANDS
3 elif CONDITION ; then
4 COMMANDS
5 else
6 COMMANDS
7 fi

2.6.2 Boucles
Il y a deux façons de faire des boucles dans le shell. Elles ont des syntaxes similaires :
— while : Tant que la condition est vraie, la boucle tourne.
— until : Tant que la condition est fausse, la boucle tourne.
1 while CONDITION ; do
2 COMMANDS
3 done
4
5 until CONDITION ; do
6 COMMANDS
7 done

Il y a un troisième genre de type de boucle, la boucle for. Sa syntaxe est la suivante :


1 for VARIABLE in LIST ; do
2 COMMANDS
3 done

Ce type de boucle peut parcourir une liste. Tant que la liste n’est pas terminée, VARIABLE prend pour chaque tour de
boucle une nouvelle valeur de LIST. LIST est une séquence de mots séparés par l’IFS actuel (Internal Field Separator ). Le
IFS détermine comment le shell reconnaît les champs ou limite les mots lors de l’interprétation des chaînes. Par défaut,
l’IFS est l’espace, la tabulation et le retour à la ligne, mais nous pouvons le changer. Par exemple, donnez-lui la valeur ’ :’
pour extraire des informations de $PATH.

2.6.3 switch case


Le shell a un autre type de structure de contrôle appelée swich case. Sa syntaxe est la suivante :
1 case WORD in
2 PATTERN1 )
3 EXPRESSION ;;
4 PATTERN2 | PATTERN3 )
5 EXPRESSION ;;
6 * )
7 DEFAULT EXPRESSION ;;
8 esac

2.6.4 Test
Le shell contient un builtin nommé test. Ce builtin permet de tester une condition sur des variables, des valeurs
numériques et / ou des fichiers. Il renvoie 0 si la condition est vérifiée, 1 sinon.

Cette builtin a deux syntaxes possibles :


1 if test -n ’ toto ’; then
2 COMMANDS
3 fi
4
5 if [ -n ’ toto ’ ]; then
6 COMMANDS
7 fi

Avertissement : Soyez conscient des espaces lors de l’utilisation de la seconde syntaxe.

Voici une liste rapide des options les plus courantes :

-n str Vérifiez que la chaîne de caractères n’est pas vide ou inexistante


-z str Vérifiez que la chaîne n’est pas vide ou inexistante
str1 = str2 Teste si la chaîne est identique
str1 != str2 Teste si les chaînes sont différentes
int1 -eq int2 Teste si deux entiers ont la même valeur
int1 -lt int2 Teste si int1 est inférieur à int2
int1 -ge int2 Teste si int1 est supérieur ou égal à int2
-e file Vérifier si un fichier existe
-d file Vérifiez si le fichier est un répertoire
-x file Vérifiez si le fichier existe et s’il est exécutable (ou traversable s’il s’agit d’un dossier)

8
2.7 Exercise : salutation.sh
Commandes autorisées : builtins, date, cut

Créez un script shell qui, en fonction de l’heure actuelle, affiche :


— "Good morning !" de 01h00 à 11h00.
— "Good afternoon !" de 12h00 à 18h00.
— "Good evening !" de 19h00 à 00h00.

2.8 Exercise : count_files.sh


Commandes autorisées : builtins, cut

Écrivez les commandes pour répondre aux questions suivantes :


— Combien y a-t-il de fichiers dans le répertoire /dev/ ?
— Lister les groupes dans /etc/group

2.9 Fonctions
Les fonctions sont comme des petits shell scripts Les arguments peuvent être accédés via des variables spéciales, $1, ..., $9.
Une fonction possède une valeur de retour.
1 $ bigger () { du $1 /* | sort -n ; }
2 $ cd test ; bigger .
3 4 ./ AUTHORS
4 4 ./ doc
5 4 ./ src
6 12 ./ README
7 28 ./ TODO
8 $

— du : estime l’espace disque utilisé pour le fichier


— sort : trie

2.10 Globbing
Parfois, tu devras appliquer le même traitement à un grand nombre de fichiers. Il serait très fastidieux de lister tous les
fichiers à la main. Le globbing te permet d’exprimer les noms de fichiers sous la forme de patterns. Un pattern est une
chaîne de caractères, il décrit certaines caractéristiques d’un nom de fichier. Par exemple, nous pouvons faire correspondre
le nom des fichiers avec au moins 8 caractères, la deuxième lettre est un ’t’ et les lettres 4 et 6 sont des voyelles. Pour cela,
nous utilisons wildcards ou metacharacters. Ce sont des caractères spéciaux dans le contexte de globbing, représentant un
ou plusieurs caractères.

Voici une liste de ces métacaractères et de leurs significations.

? 1 caractère
* 0 plus de caractères
[aeiouy] 1 des caractères entre les crochets
[a-t] 1 des caractères entre ’a’ et ’t’, les limites sont inclues
[ˆabc] ou [ !abc] 1 caractère autre que ceux mentionnés
1 $ echo /[ a - e ]??
2 / bin / dev / / etc
3 $ echo / h * e
4 / home

2.11 Quoting
Le quoting change la façon dont le shell va interpréter certaines expressions. Pour ce faire, entourez simplement l’expression
de guillemets simples, doubles ou inversés. Chacun de ces symboles a un comportement différent.

9
2.11.1 Double quotes (")
— Inhibe le globbing du shell
— Assemble plusieurs mots dans un seul argument 3
— Autorise l’expansion de variable, c’est-à-dire le remplacement du nom de la variable par sa valeur

2.11.2 Simple quotes (’)


Les simples quotes ont le même comportement que les doubles quotes, mais ils inhibent l’expansion des variables

2.11.3 Back-quotes (‘)


Les back-quotes ont un comportement différent des deux types de quotes précédents. Ils permettent d’exécuter une
commande dans une sous-shell. La commande entre les back-quotes est remplacée par la sortie standard de cette
commande. Ainsi, il est possible de récupérer la sortie standard dans une variable. La valeur de retour de la commande est
stockée dans la variable $ ? . Il est possible de combiner différents types de quoting.
1 $ echo " Hi ␣ $USER , ␣ we ␣ are ␣ the ␣ ‘ date ‘. "
2 Hi jules . aubert , we are the Mon Oct 2 17:41:28 CEST 2017.

3. Utile si l’argument possède des espaces

10
Chapitre 3

Shell script avancé

3.1 Redirections
Dans le monde UNIX, tout est un fichier : l’écran, le disque dur, la mémoire du logiciel que vous utilisez, et bien sûr les
fichiers sur le disque dur 1 . Il est courant de vouloir que le shell écrive dans des fichiers au lieu de les afficher à l’écran. La
redirection permet la redirection des flux d’entrée / sortie. Ils sont utilisés, par exemple, pour s’assurer que la sortie
standard d’un programme est redirigée vers un fichier 2 .
— CMD > file : CMD la sortie est écrite dans le fichier. Si ce fichier n’existe pas, il est créé. S’il existe déjà, son
contenu est écrasé
— CMD >> file : ajoute CMD la sortie dans le fichier. Si le fichier n’existe pas, il est créé
— CMD < file : le contenu du fichier est utilisé comme entrée standard pour CMD.
Nous pouvons aller encore plus loin en jouant avec des descripteurs de fichiers, pour rediriger certaines entrées et / ou
sorties, mais pas toutes. Pour indiquer depuis quel descripteur de fichier nous voulons rediriger, entrez simplement son
numéro avant le symbole de redirection. Pour indiquer vers quel descripteur de fichier nous voulons rediriger le flux, il suffit
d’entrer le numéro du descripteur suivant le symbole de redirection.
1 $ echo foo > file
2 $ cat file
3 foo
4 $ echo bar >> file
5 $ cat file
6 foo
7 bar
8 $ cat < file
9 foo
10 bar
11 $ # redirecting stderr to / dev / null
12 $ badcommand 2 > / dev / null
13 $ # redirecting both outputs to / dev / null
14 $ badcommand & > / dev / null
15 $ # redirecting stderr to stdout
16 $ command 2 > $1
17 $ cat << EOF >> file
18 this is a tiny text editor ! it can be useful
19 to write reports in a shell script .
20 EOF
21 $ cat file
22 this is a tiny text editor ! it can be useful
23 to write reports on a shell script .
24 $

Note : la redirection est une extension Bash.

3.2 Sous-shells, source et exec


3.2.1 Sub-shells
La seul information qu’on peut retrouver d’un sous-shell, c’est sa sortie standard et son code de retour. On ne peut pas
retrouver la sortie d’erreur, et les variables définies dans le sous-shell ne sont pas visibles dans le shell parent. Les
sous-shells sont un moyen d’exécuter des commandes qui intéragissent légèrement avec le shell courant. Si nous voulons plus
d’interaction avec le shell courant, nous devons trouver une autre solution.

Il y a deux façons de démarrer un sous-shell : ‘COMMAND‘ or $(COMMAND).


1. Les répertoires sont également représentés comme des fichiers spéciaux
2. /dev/null est un fichier spécial qui supprime tout ce qui y est ajouté

11
1 $ toto = foo
2 $ echo $toto
3 foo
4 $ echo $ ( toto = bar ; echo $toto )
5 bar
6 $ echo $toto
7 foo

3.2.2 Source
source (ou simplement ’.’) est un builtin qui t’autorise à lancer un shell script dans le shell courant. Cette fonctionnalité
est utilisé pour initialiser des variables, des fonctions ou des alias.

3.2.3 Exec
L’utilité première du builtin exec est de replacer le shell par des commandes en arguments. Cette builtin est aussi utilisé
pour faire des redirections vers de nouveaux descripteurs de fichier pour le shell courant si aucune commande n’est spécifiée.
1 $ exec 3 >/ tmp / file . txt
2 $ echo " The ␣ shell ␣ is ␣ good
3 ␣ ␣ >␣ but ␣ with ␣ exec
4 ␣ ␣ >␣ it ␣ goes ␣ really ␣ far " >&3
5 $ echo " Hell ␣ yeah " >&3
6 $ cat / tmp / file . txt
7 The shell is good but with exec , it goes really far
8 Hell yeah

3.3 I/O avancé


Il est intéressant pour certains scripts shell d’interroger l’utilisateur et lui demander d’entrer des informations pendant
l’exécution du script. Pour cela, nous utilisons le builtin read qui lit sur l’entrée standard et stocke les mots dans les
variables dont les noms sont des arguments lus. S’il y a plus de mots que d’arguments passés à read, la commande stocke
l’extra dans la dernière variable. Pour séparer des mots, read utilise l’IFS.
1 $ echo $PATH
2 / usr / local / bin :/ usr / bin :/ bin :/ opt / bin :/ home / jules . aubert / mybin
3 $ echo $PATH > PATH . file
4 $IFS = ’: ’
5 $ read p1 p2 p3 p4 < PATH . file
6 $ echo $p1
7 / usr / local / bin
8 $ echo $p2
9 / usr / bin
10 $ echo $p3 $p4
11 / bin / opt / bin / home / jules . aubert / mybin

Pour lire un fichier ligne par ligne :


1 # !/ bin / sh
2
3 while read line ; do
4 echo $line
5 done < file . txt

Et mot à mot :
1 # !/ bin / sh
2
3 while read line ; do
4 for word in $line ; do
5 echo $word
6 done
7 done < file . txt

12
Chapitre 4

Divers (vive le vent, vive le vent...)

4.1 Commandes utiles


tr Remplace ou supprime un caractère
head Affiche les premières lignes d’un fichier
tail Affiche les dernières lignes d’un fichier
cat Affiche le contenu d’un fichier
time Chronomètre le temps d’exécution d’un programme
grep Cherche un pattern dans un fichier
cut Couper une ligne en champs en fonction d’un délimiteur
paste Coller une ligne de champs séparés avec un délimiteur
diff Affiche les différences entre deux fichiers
kill Tueu n processus
sort Trie un fichier
wc Compte le nombre de lignes, mots et caractères d’un fichier
uniq Supprime les doublons
man Affiche les entrées du manuel pour une application
date Donne la date actuelle
screen Terminal virtuel dont vous pouvez vous détacher
bc Evaluateur d’expressions arithmétiques, extensible aux réels
xargs Construit et exécute les commandes à partir de l’entrée standard
dirname Conserve uniquement la partie de répertoire d’un chemin
basename Élimine le chemin et le suffixe d’un nom de fichier

4.2 Liens utiles


— http://www.shellunix.com
— http://www.livefirelabs.com/unix_tip_trick_shell_script/unix_tip_archive.htm
— http://cli.asyd.net

4.3 Références
http://www.multicians.org/shell.html The Origin of the Shell
http://pubs.opengroup.org/onlinepubs/9699919799/ POSIX
http://www.unix.org/version4/ Single UNIX Specification

13
Chapitre 5

Expressions régulières

Les expressions régulières, appelées regexp ou regex, sont un support essentiel pour de nombreux utilitaires UNIX tels que
grep et sed, que nous étudierons.

Une expression régulière est un pattern qui décrit un ensemble de chaînes. Les expressions régulières sont construites en
tant qu’arithmétique : elles utilisent des opérateurs différents pour combiner des expressions plus petites.

Il existe plusieurs types d’expressions régulières : les basiques et les étendues. La plupart des utilitaires offrent l’un ou
l’autre via des options de ligne de commande. La différence entre ces deux formes consiste principalement à préfixer
certaines constructions par un backslash (’\’) comme nous le verrons plus bas.

Une expression régulière est mappée à une chaîne de caractères, caractère par caractère.

Note : Dans les exemples, j’utilise l’opérateur =∼ (la notation utilisée en Perl et Ruby), ce qui signifie un test de
correspondance (un match) : le terme gauche étant la chaîne de test et le droit l’expression régulière.

5.1 Regex basiques


Les blocs de construction sont les expressions régulières correspondants à un seul caractère.
1 ABCD =~ ABCD = > match
2 abcd =~ ABCD = > mismatch
3 wyzABCDxyz =~ = > match ( with the substring )

Certains caractères ont des significations particulières : ils sont appelés des métacaractères.

5.1.1 Le point .
Le métacaractère point (.) représente une instance de n’importe quel caractère :
1 AxB =~ A . B = > match
2 A B =~ A . B = > match
3 A123B =~ A . B = > mismatch
4 A =~ A . = > mismatch
5 AxB =~ A \. B = > mismatch
6 A . B =~ A \. B = > match

5.1.2 Début ˆ et fin $


Les deux symboles spéciaux ˆ et $ représentent respectivement, le début et la fin d’une chaîne de caractères. Elles ne sont
pas mappées sur un caractère existant mais plutôt sur une chaîne de caractères vide. Par exemple ˆa signifie "n’importe
quelle chaîne qui commence par un ’a’" ; bˆ signifie "n’importe quelle chaîne finissant avec un ’b’"
1 abcde =~ ^a = > match
2 bacde =~ ^a = > mismatch
3 abcde =~ e$ = > match
4 abcde =~ ^ a$ = > mismatch
5 a =~ ^ a$ => match

Attention : Les symboles ˆ et $ reprennent leur signification littérale si ils ne sont pas au début (ou respectivement la fin)
de la regex :

14
1 A$B =~ A$B = > match
2 A ^ =~ A ^ = > match
3 ( empty string ) =~ ^ $ = > match
4 ^ $ =~ ^ $ = > mismatch
5 b$ =~ b$ = > mismatch
6 b$ =~ b \ $ = > match

5.1.3 Alternative
Le caractère |, précédé d’un backslash \, représente une alternative entre deux éléments :
1 abd =~ ab \| cd = > match
2 acd =~ ab \| cd = > match
3 axd =~ ab \| cd = > mismatch
4 aed =~ ab \| c \| ed = > match

5.1.4 Liste
Les listes sont des raccourcis aux alternatives : au lieu d’écrire a\|b\|c, on peut écrire [abc] :
1 abd =~ a [ bce ] d = > match
2 acd =~ a [ bcd ] d = > match
3 axd =~ a [ bce ] d = > mismatch

Attention : Dans une liste, les métacaractères reprennent leur signification littérale
1 \ =~ [.*\] = > match
2 [ =~ [] abc [] = > match
3 ] =~ [] abc [] = > match
4 a =~ [] abc [] = > match

Si le premier caractère d’une liste est ˆ, la signification de la liste est inversée et devient "tout excepté un caractère de la
liste" :
1 a =~ [^ abc ] = > mismatch
2 e =~ [^ abc ] = > match

5.1.5 Intervalle
Les intervalles sont des raccourcis pour décrire des caractères successifs dans une liste.
1 z3 =~ [a - z ][0 -9] = > match
2 zz =~ [a - z ][0 -9] = > mismatch
3 a4 =~ a [1 -35] = > mismatch
4 a5 =~ a [1 -35] = > match
5 a6 =~ a [1 -35 -7] = > match

Ici, [1-35] ne signifie pas "n’importe quel nombre de 1 à 35" mais "n’importe quel caractère entre 1 et 3 ou 5". Sois sûr de
lire caractère par caractère.

Pour utiliser le caractère - dans une liste, il doit être placé en première position.
1 - =~ [ -A - C ] = > match
2 B =~ [ -A - C ] = > match

Attention : L’ordre des caractères est déterminée par le code ASCII.

5.1.6 Classe
Les classes sont des intervalles prédéfinies, qui peuvent être paramétrées par la variable d’environnement LC_ALL, pour
répondre à différents encodages de caractères. L’encodage qui nous intéresse est ISO-8859-1, réalisé ) travers
LC_ALL=fr_FR.

La syntaxe des nombreueses classes est [ :class_name :] dans une liste.

15
Nom Signification ASCII ISO-8859-1
alpha Lettres alphabétiques dans la [A-Za-z] [A-Za-zÁÀÄ...ùûý]
locale courante
digit Nombres décimaux [0-9] ditto ASCII
xdigit Nombres hexadécimaux [0-9A-Fa-f] ditto ASCII
alnum Nombres ou lettres [ :alpha :][ :digit :] [ :alpha :][ :digit :]
alphanumériques
lower Lettres minuscules dans la [a-z] [a-záàäâ...üý]
locale courante
upper Lettres majuscules dans la [A-Z] [A-ZÁÀÄ...ùûý]
locale courante
blank Caractères blancs [ \t] ditto ASCII
space Caractères d’espacement \t\n\f\r\v ditto ASCII
punct Signes de ponctuations []- !"#$%&’()*. :+ ditto ASCII
;\<=> ?@ˆ_{}∼
graph Symboles ayant une réprésentation [[ :alnum :][ :punct :]] ditto ASCII
graphqiue (sauf l’espace)
print Caractères imprimables [[ :graph :][ :space :]] ditto ASCII
cntrl Caractères de contrôles ASCII code <31 and 127 ditto ASCII
Si tu veux plus d’information, réfère toi au man de regex(7) et wctype(3).

5.1.7 Répétition
Pour décrire la répétition, nous avons les métacaractères suivants :
— * zéro ou plus d’occurrences de l’élément précédent
— + une ou plus d’occurrences de l’élément précédent
— ? zéro ou une occurrence de l’élément précédent
— {n,m} au moins n et m occurrences de l’élément précédent
— {n,} au moins n occurrences de l’élément précédent
— {n} exactement n occurrences de l’élément précédent
1 ac =~ ab \+ c = > mismatch
2 abc =~ ab \+ c = > match
3 abbbc =~ ab \+ c = > match
4
5 ac =~ ab * c = > match
6 abc =~ ab * c = > match
7 abbbc =~ ab * c = > match
8
9 ac =~ ab \? c = > match
10 abc =~ ab \? c = > match
11 abbbc =~ ab \? c = > mismatch
12
13 abc =~ ab \{2 ,3\} c = > mismatch
14 abbc =~ ab \{2 ,3\} c = > match
15 abbbc =~ ab \{2 ,3\} c = > match
16 abbbbc =~ ab \{2 ,3\} c = > mismatch

Note que la répétition de caractères combinée à des métacaractères représentants des alternatives ne s’attend pas à ce que
toutes les occurences soient le même caractère :
1 a12345c =~ a .\{5\} c = > match
2 axyzxc =~ a [ xyz ]\+ c = > match

5.1.8 Groupement
Nous pouvons grouper différents caractères dans un seul élément avec (). Cette forme est très utile, spécialement dans la
combinaison avec d’autres métacaractères :
1 123 =~ \(123\) \{2\} = > mismatch
2 123123 =~ \(123\) \{2\} = > match
3
4 abc =~ \( abc \) \|\( def \) = > match
5 def =~ \( abc \) \|\( def \) = > match
6 xyz =~ \( abc \) \|\( def \) = > match
7
8 AxBAyB =~ \( A . B \) \{2\} = > match

5.1.9 Rétro référence


La valeur correspondante par un groupe peut être réutilisée dans l’expression régulière suivante par la construction \N,
avec N le nombre représentant le N-ième groupe :

16
1 axbcyabc =~ \(.\) x \(..\) y \1\2 = > match
2 axbcyabd =~ \(.\) x \(..\) y \1\2 = > mismatch

Note que les groupes peuvent être nichés dans ce cas, le N-ième groupe est défini par la N-ième parenthèse :
1 aceacec =~ \([ ab ]\([ cd ]\) [ ef ]\) \1\2 = > match
2 acecace =~ \([ ab ]\([ cd ]\) [ ef ]\) \1\2 = > mismatch

5.2 Regex étendues


Les expressions régulières étendues ont la même puissance que les expressions régulières basiques, seule la syntaxe diffère :
elle omet le caractère \ pour certains constructions.

Signification Symbole de la regex basique Symbole de la regex étendue


Caractère générique . .
Début de ligne ˆ ˆ
Fin de ligne $ $
Alternative \| |
Liste de caractère [] []
Classe de caractère [ :class :] [ :class :]
0 ou plus d’occurrences de * *
l’élément précédent
1 ou plus d’occurrences de \+ +
l’élément précédent
0 ou une occurrence de \? ?
l’élément précédent
Au moins n et au plus m \{n,m\} {n,m}
occurrences de l’élément
précédent
Au moins n occurrences de \{n,\} {n,}
l’élément précédent
Aau plus m occurrences de \{0,m\} {0,m}
l’élément précédent
Exactement n occurrences de \{n\} {n}
l’élément précédent
Groupement de caractères \{(\) ()
Rétro référence du n-ième groupe \n \n
Un caractère de préfixe spécial pour \ \
prendre sa valeur littérale

17
Chapitre 6

Grep

6.1 Introduction
grep est un outil qui recherche dans des fichiers donnés (ou à partir d’une entrée standard si aucun fichier n’est donné, ou
si le flag - est donné), en utilisant une ligne de commande, des lignes correspondant à une expression régulière spécifique.
Par défaut, grep affiche des lignes qui correspondent à une expression régulière simple donnée en paramètre.

Voici les options communes de ’grep’ :


— -E utilise les expressions régulières étendues
— -v affiche les lignes qui ne correspondent pas à la chaîne de caractères
— -i ignore la casse (majuscule/minuscule)
— -c compte le nombre de lignes contenant la chaîne de caractères
— -n numérote chaque ligne contenant la chaîne de caractères
— -x affiche les les lignes correspondants exactement à la chaîne de caractères
— -l affiche les noms des fichiers qui contiennent la chaîne de caractères
— -r effectue une recherche récursive
— -A NUM affiche NUM lignes après la ligne détectée
— -B NUM affiche NUM lignes avant la ligne détectée
— -C NUM affiche NUM lignes avant et après la ligne détectée, donnant à ta recherche un peu de contexte

6.1.1 Percée
Voici quelques questions à mettre en pratique avec le fichier /etc/passwd :
— Comment avoir toutes les lignes commençant avec le caractère ’x’ ou qui contiennent la chaîne de caractères “jules” ?
— Même question qu’au dessus, avec les expressions régulières étendues.
— Comment afficher les lignes qui ne contiennent pas le pattern "sh" ?
— Comment afficher le nombre de lignes qui contiennent le mot "root" ?
— Comment afficher le numéro de la ligne qui contient le pattern "root" ?
Avertissement : Rappelle-toi que le shell étend les arguments avant d’exécuter la commande.
Prenez l’habitude de protéger vos expressions régulières par des quotes.

18
Chapitre 7

Sed

sed est un éditeur de flux interactif : il lit une par une les lignes d’un fichier (ou de l’entrée standard) applique les
commandes d’édition et retourne le résultat sur la sortie standard. Par défaut, il ne modifie pas le fichier traité mais
l’affiche sur la sortie standard. L’atout de sed est de pouvoir être utilisé dans un pipeline.

7.1 Syntax
Pour appeler sed :
1 $ sed -e ’ program ␣ sed ’ file -a - deal

ou
1 $ sed -f program - file file - treat

Voici plusieurs exemples d’appels à sed :


1 $ sed " s / foo / bar /; ␣ s / toto / titi / g " file
2 $ sed -e ’s / foo / bar / ’ -e ’s / titi / toto ’ file
3 $ echo ’s / foo / bar ’ > / tmp / prog . sed && sed -f / tmp / prog . sed -e ’s / titi / toto ’ file
4 $ < file sed " s / foo / bar /; ␣ s / toto / titi / g "

Il est également possible de créer des scripts sed, pour cela il faut remplacer le traditionnel shebang # !/bin/sh par
# !/bin/sed -f.

7.2 Méchanique
La mécanique de sed est la suivante :
1. Lit une ligne sur le flux d’entrée (jusqu’à rencontrer un caractère de fin de ligne)
2. Traitement de la ligne en la passant à toutes les commandes rencontrées dans le script
3. Affiche la ligne résultante à la sortie standard à moins que sed ne soit invoqué avec l’option -n
Il est également possible d’appeler sed avec l’option -i. Dans ce cas, les commandes modifient directement le fichier entré
au lieu de l’afficher sur la sortie standard. Certains arguments peuvent être ajoutés aux suffixe -i (ça ne fonctionne pas avec
toutes les versions de sed).

Chaque instruction d’un fichier sed est composée d’une commande ou d’un bloc de commandes (ajouter une ligne,
supprimer une ligne, remplacer une chaîne de caractères, etc.) et peut être précédée par une adresse pour appliquer la
commande à un sous-groupe de lignes.

Exemple :
1 # !/ bin / sed - rf
2 # This is a comment
3 /[ a - z ]+[ a - z0 -9]*/ {
4 y /0123456789/1234567890/
5 p
6 }
7 d

Par défaut, sed utilise les expressions régulières basiques. Pour utiliser les expressions régulières étendues (comme grep), il
faut invoquer sed avec l’option ’r.

19
7.3 Commandes simples
7.3.1 La commande de substitution : s
La fonction de substitution change la première occurence d’une chaine de caractères avec une autre. C’est de loin la
commande la plus utilisé dans les scripts sed.

La syntaxe générale est :


1 s / pattern / replacement / options

— pattern est une expression régulière (simple ou étendue selon l’option donnée à l’invocation de sed, simple par défaut)
— replacement est une chaine de caractère qui remplace pattern dans le résultat. Cette chaine peut contenir deux
wildcards :
— & sera remplacé la chaine complète qui a été mappée par pattern
— \n, où n est un chiffre entre 1 et 9 est remplacé par le n-ème groupe dans le pattern. Un groupe correspond à ce
qu’il y a entre crochets dans le pattern.
— Options disponibles :
— G : remplace tous les patterns rencontrés dans la ligne actuelle ;
— N : remplace seulement la N-eme occurrence du pattern dans la ligne ;
— I : ne pas être sensible à la casse ;
— P : affiche la ligne à la sortie standard si une substitution est effectuée ;
— W fichier : écrit la ligne vers ’fichier’ si une substitution est effecutée.
Il peut y avoir plusieurs options simultanément.

Voici des exemples :


1 # changes the first occurrence of the string ‘ toto ’ by ‘ TOTO ’
2 # ( the first string ‘foo ’ encountered in text only )
3 sed ’s / toto / TOTO ’ file
4
5 # changes the third occurrence of the string ‘foo ’ to ‘’ TOTO ’
6 # ( the third string ‘foo ’ encountered in text only )
7 sed ’s / toto / TOTO /3 ’ file
8
9 # changes all occurrences of the string ‘ foo ’ to ‘ TOTO ’
10 # ( all strings foo encountered are changed )
11 sed ’s / toto / TOTO / g ’ file
12
13 # when substituting the input line is printed to ‘ result ’ file
14 sed ’s / toto / TOTO / w ␣ result ’ file

La fonction de substitution peut, évidemment, être utilisée avec une expression régulière.
1 # replaces all ’ Strawberry ’ or ’ strawberry ’ stringd by ’ STRAWBERRY ’
2 sed -e ’s /[ SS ] trawberry / STRAWBERRY / g ’ file
3
4 # replaces all ’ Stawberry ’ or ’ strawberry ’ strings
5 # with ’ _Strawberry_ ’ or ’ _strawberry_ ’
6 sed -e ’s /[ Ss ] trawberry / _ & _ / g ’ file

Note : Tu peux utiliser n’importe quel type de séparateur (pas juste ’/’). Pour reprendre son utilisation normale dans les
patterns, il doit être précédé par le caractère
textbackslash. C’est pareil pour la commande y.
1 $ sed -e ’s , titi ,/ titi , g ’ file
2 $ sed -e ’ ,: ,\ , , g ’ file
3 $

7.3.2 La commande de suppression : d


La commande de suppression d supprime la ligne courante et commence immédiatement un nouveau cycle sans exécuter
d’autres commandes.

7.3.3 La commande de remplacement : y


La commande y/src-chars/dest-chars transpose tous les caractères de from src-chars avec leur équivalence dans
dest-chars, comme le fait la commande UNIX tr.

20
7.3.4 La commande d’affichage : p, l and -
La commande p (print) affiche la ligne selectionnée sur la sortie standard. C’est essentiel lorsque sed est invoqué avec
l’option -n.

La commande l (list) affiche la ligne sélectionnée sur la sortie standard, avec le caractère de contrôle en clair (\t au lieu de
tab, etc.) et en code ASCII (deux chiffres en octal) pour les caractères non imprimables.
1 $ echo -e ’ te \ tst ’| sed -n ’p ’
2 te st
3 $ echo -e ’ te \ tst ’| sed -n ’l ’
4 te \ tst$
5 $

La commande = donne le numéro de la ligne sélectionée sur la sortie standard.

7.4 Adresses
La plupart des commandes peuvent être précédées d’une adresse, qui a comme rôle d’indiquer à quelle ligne appliquer la
commande. Les différents formats d’adresse sont utilisés comme suit :
— le nombre ’ n’ spécifie que seulement la n-eme ligne du ficher est concernée par la commande (les lignes commencent
à 1) ;
— ’ $’ est la dernière ligne du dernier fichier entré ;
— ’/ expression/’ sélectionne toutes les lignes contenant l’expression régulière ;
— ’% expression%’ a le même effet que le format de l’adresse précédente mais offre l’opportunité d’entourer
l’expression régulière en utilisant un caractère différent que le slash / (n’importe quel caractère peut être utilisé au
lieu de %) ;
— ’ n, m’ sélectionne toutes les lignes depuis la ligne n jusqu’à la ligne m ;
— ’ addr1, addr2’ sélectionne toutes les lignes entre le pattern addr1 et le pattern addr2. addr1 peut être remplacé
par le numéro d’une ligne. Cependant, la recherche pour addr2 commencent seulement après la ligne addr1 si
addr2 est une regex ;
— ’ addr !’ supprime toutes les lignes sélectionnées par addr, et sélectionne les autres.
Voici quatre exemples qui appellent la commande ’p’ sur les lignes sélectionnées :
1 / test / p # prints lines containing " test "
2 4 ,8 p # prints lines 4 to 8
3 / if / ,/ fi / p # prints lines between the pattern ’if ’ and ’fi ’
4 $!p # prints all lines except the last

7.4.1 Commandes de blocs : ’{}’


On peut grouper plusieurs commandes en un seul bloc, en utilisant les crochets ’{}’ et en séparant chaque commande par
un sut de ligne ou un point-virgule.

C’est principalement utile lorsque plusieurs commandes doivent être appliquées aux mêmes lignes.

7.4.2 Bloc de remplacement : ’c’


La commande ’c’ s’utilise ainsi :
1 address c \ text

Elle peut remplacer les lignes associées dans le texte donné. Par exemple :
1 / fool / c \ censored line

Cette commande remplacera toute ligne contenant "fool" par le texte "censored line"

7.5 Labels
Les labels sont utilisés pour faire des boucles et des tests. Un label peut être défini avec cette syntaxe : :label (en
remplaçant label par le nom de ton choix).

Deux contrôles mettent en faveur l’utilisation des labels :


— la commande ’b label ’ cause le saut immédiat à la position du script où label est défini (si label est omit, sed saute
plus haut au début du script, affiche la ligne traitée si l’option ’-n’ n’a pas été donnée, et lit une nouvelle ligne de
donnée) ;

21
— la commande ’t label ’ cause un saut dans le script à la position où label est défini seulement si la dernière commande
de substitution modifie le pattern.

7.6 Commandes avancées


Il y a d’autres commandes, qui ne seront pas développées ici, qui prennent de la place mémoire pour effectuer de multiples
tâches avancées. Ca peut, par exemple, s’exécuter sur plusieurs lignes simultanément.

Il y a aussi d’autres extensions GNU des différentes commandes présentées. Bien que souvent utiles, il est recommandé de
ne pas les utiliser pour garder la portabilité de vos scripts.

22
Chapitre 8

Exercises

8.1 Mise en route


Ton shell est capable de te donner quelques informations à propos de l’exécution de ton script. Cela peut s’avérer utile si
vous souhaitez déboguer vos scripts. Pour l’activer, passe simplement le paramètre -x à sh :
1 sh -x myscript . sh
2 ...
3
4 OR
5 # !/ bin / sh
6 # No need to debug
7 set -x
8 # Debug mode on
9 set + x
10 #
11 # Next part of the script
12 ...

8.2 squeeze.sh
Commandes autorisées : builtins, tr

Ecris un script qui remplace tous les espaces contiguës par un seul underscore ’_’ et tous les astérisques ’*’ par un point ’.’
dans l’argument donné en ligne de commandes. Note : ** devient ..
1 $ ./ squeeze . sh ’ my ␣ ␣ ␣ ␣ ␣ source ␣ ␣ file ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ ␣ * c ’
2 my_ source_file . c

Lis le man avec attention, un option spécifique de tr peut se rendre très utile.

8.3 get_line.sh
Commandes autorisées : head,tail

Ecris un script qui affiche la nième ligne d’un fichier. Le premier argument donné au script sera le nom du fichier, et le
second la ligne à obtenir. Si la ligne donné en argument est trop haute, le script affichera simplement la dernière ligne.
1 $ cat file . txt
2 Line number 1
3 Line number 2
4 Line number 3
5 Line number 4
6 Line number 5
7 Line number 6
8 $ ./ get_line . sh file . txt 3
9 Line number 3

8.4 log.sh
Commandes autorisées : builtins, tee

Ecris un script qui prend une commande et ses arguments en entrée, et l’exécute. Tu as besoin de :
— Rediriger sa sortie standard dans le fichier log.out ;

23
— Afficher sa sortie standard sur la sortie standard ;
— Rediriger sa sortie d’erreur dans le fichier log.err ;
— Rien ne doit être affiché sur la sortie d’erreur.
Exemple
1 $ log . sh / bin / echo toto
2 toto
3 $ cat log . err
4 $ cat log . out
5 toto
6 $ ./ log . sh ls unknown
7 $ cat log . out
8 $ cat log . err
9 ls : unknown : No such file or directory

8.5 sum.sh
Commandes autorisées : builtins, sed, tr

Ecris un script qui calcule la somme de tous ses arguments, 0 s’il n’y en a aucun. On suppose que chaque argument est un
nombre entier valide.
Les détails de l’opération doivent être affichés, suivis du résultat.
1 $ ./ sum . sh 3 4 5
2 3 + 4 + 5 = 12
3 $ ./ sum . sh
4 0 = 0
5 $ ./ sum . sh 3
6 3 = 3

8.6 Spell checker


Commandes autorisées : builtins, grep, sed, sort, cat, tr, head

Le fichier /usr/share/dict/words contient un dictionnaire pour la langue Anglaise. Nous voulons vérifier qu’un texte ne
contienne pas d’erreur. Ecris un script qui montre dans l’ordre alphabétique tous les mots donnés dans un fichier qui ne
sont pas présents dans le dictionnaire. La vérification ne soit pas être sensible à la casse.

Conseils :
— Le script ne devrait faire qu’une dizaine de lignes. Tu peux en avoir plus si tu veux, mais s’il te plait, ne part dans
du code long et compliqué.
— Lire le man est toujours une bonne idée.

8.7 Sed
Pour ces quelques exercices, tu dois programmer exclusivement avec ses. Tu peux écrire les commandes dans un fichier
’.sed’ ou directement dans la ligne de commande de ton shell.

8.7.1 L’espace fini


Tu veux supprimer les espaces en fin de ligne d’un fichier. Ecris un script pour accomplir cette tâche. Souviens toi aussi de
supprimer les tabulations en fin de ligne.
1 $ cat -e test
2 Line 1 $
3 Line 2 $
4 Line 3 $
5 $ sed -f deletetw . sed test | cat -e
6 Line 1 $
7 Line 2 $
8 Line 3 $
9 $

8.7.2 Grep
Tu dois utiliser sed au lieu de grep. Ecrit un script sed qui n’affiche que les lignes qui correspondent à l’expression régulière
de ton choix. Puis édite le script pour simuler le ’-v’ de grep.

24
8.7.3 Head
Tu dois simuler la commande head en utilisant sed. Ecris un script sed qui affiche les cinq premières lignes du fichier.

8.7.4 Head | Tail


Maintenant, tu veux afficher quelques lignes au milieu du fichier (c’est équivalent à appeler head suivi de tail). Ecris un
script qui n’affiche que les lignes 25 à 30.

8.8 Compter en binaire


Tu dois écrire un script qui compte en nombre binaire. Ton script doit lire un nombre donné (sur l’entrée standard) et
affiche son successeur.

Astuce : Pour gérer la sauvegarde, il peut être utile de remplacer le caractère ’1’ de la fin avec un autre caractère,
temporairement.
1 $ echo ’ 10 ’ | ./ binary . sed
2 11
3 $ echo ’ 11 ’ | ./ binary . sed
4 100
5 $ echo ’ 101001 ’ | ./ binary . sed
6 101010
7 $

Propose un patch au script pour afficher tous les nombres binaires de 0 à 1100.
1 $ echo ’0 ’ | ./ bcompteur . sed
2 0
3 1
4 10
5 11
6 100
7 101
8 110
9 111
10 1000
11 1001
12 1010
13 1011
14 1100

25

Vous aimerez peut-être aussi