Vous êtes sur la page 1sur 14

Petit tutoriel de programmation shell (bash)

Frédéric Guinand
Année Spéciale - IUT du Havre

1
Table des matières
1 Variables 3
1.0.1 Un petit exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.0.2 Variables internes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.0.3 Variables définies par l’utilisateur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.0.4 Utilisation des quotes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1 Exemples complémentaires . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2 Arguments ligne de commande 6

3 Evaluation d’expressions arithmétiques 6


3.1 Commandes et opérateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.3 Commande expr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

4 Structures de contrôle conditionnelles 7


4.1 Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
4.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

5 Opérateurs de comparaison 8

6 Structures de contrôle itératives 10


6.1 Boucles for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
6.1.1 Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
6.1.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
6.2 Boucles while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
6.2.1 Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
6.2.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

7 Expressions régulières 11

8 Tableaux 12
8.1 Présentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
8.2 Initialisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
8.3 Lecture des éléments d’un tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
8.4 Taille d’un tableau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

9 Lecture entrée standard 14

2
1 Variables
Un script shell est un ensemble de commandes interprétées. Par convention, un script bash commence avec la
ligne :

#!/bin/bash

Cette première ligne indique à l’interpréteur de commande que le shell qui sera exécuté est un bash, et ceci,
quel que soit le shell interactif choisi par l’utilisateur pour les terminaux de commandes (xterm). Cette ligne revêt
une grande importance puisque la syntaxe des différents langages de scripts shells est différente.
Il existe deux types de variables en shell, les variables d’environnement et les variables définies explicitement
par l’utilisateur.

1.0.1 Un petit exemple

# !/bin/bash

# ce script écrit sur la sortie standard la liste des


# fichiers du répertoire courant
bienvenu=’Bonjour utilisateur ’
bonjour=$bienvenu$USER
echo
echo $bonjour
echo ’Votre répertoire courant est :’
echo ”–> $PWD <– ”
echo ’et son contenu est le suivant :’
echo
ls
echo

Le caractère # est utilisé pour les commentaires. Tout ce qui suit ce caractère n’est pas pris en compte pour
l’exécution. Il s’agit simplement d’informations qui sont ajoutées au script pour améliorer sa lisibilité.

1.0.2 Variables internes


$USER et $PWD sont des variables internes. La liste des variables internes est longue, et est partiellement
commune à la liste des variables d’environnement qui peuvent être obtenues par la commande env. Ces variables
n’ont pas à être définies par l’utilisateur, elles existent indépendamment du script. Certaines sont intéressantes :
– $HOME : répertoire racine de l’utilisateur
– $HOSTNAME : nom de la machine
– $PATH : ensemble des chemins vers les exécutables
– $PWD : répertoire courant
– $REPLY
– $SECONDS
– paramètres de position : voir Section 2.

1.0.3 Variables définies par l’utilisateur


Pour les variables définies par l’utilisateur, une affectation se fait avec le nom de la variable qui n’est pas
précédé par le symbole $ comme cela est illustré avec les variables bienvenu et bonjour.

Attention : pour une affectation, il ne doit pas y avoir d’espace entre le nom de la variable, le signe = et la valeur

Pourquoi ?
toute ligne dans un script est interprétée comme une commande par le langage de commandes, selon le format

3
classique :
nom-de-la-commande argument1 argument2 argument2

Opération sur les variables :


Pour effectuer une opération sur une variable, ce n’est pas aussi simple, il faut utiliser la commande let.

# !/bin/bash

var=1
echo ”\$var=$var”
var2=$var+1
echo ”\$var2=$var2”
let var3=$var+1
echo ”\$var3=$var3”
var4=$((var+1))
echo ”\$var4=$var4”
echo

La seconde façon de faire les choses est un peu plus compliquée il s’agit de la substitution de commande.

Substitution de commande :

Ce mécanisme vous permet de récupérer le résultat d’une commande et de le traiter comme s’il était écrit sur
une ligne de commande. Il existe deux syntaxes pour ce mécanismes, les parenthèses $(commande) et les simples
quotes (accents graves) comme ceci ‘commande‘.

# !/bin/bash
rep courant=”$(ls )”
rep audessus=‘ls ..‘
echo $rep courant
echo $rep audessus
X=‘expr 3 2 + 4‘ # expr évalue une expression arithmétique.
echo $X

1.0.4 Utilisation des quotes


L’utilisation des double quotes (”) permet l’affichage du contenu des variables qui sont contenues dans la
chaı̂ne. Dans l’exemple précédent c’est ce qui se passe avec $PWD. Par contre, les simples quotes (’) ne le per-
mettent pas. Donc, si vous manipulez des données textuelles simples dans lesquelles rien ne doit être interprété
préférez les simples quotes.
L’exemple suivant est très parlant concernant l’utilisation des quotes dans les shell. Voici deux shells apparam-
ment très proches (ils ne diffèrent que par l’utilisation de quotes dans le test) :

4
Shells
v=”” v=””
if [ -n $v ] ; if [ -n “$v” ] ;
then then
echo -n ’variable $v=’ echo -n ’variable $v=’
echo ”$v n’est pas vide” echo ”$v n’est pas vide”
fi fi
Résultats
[guinand@localhost src]$ ./exemple2.bash [guinand@localhost src]$ ./exemple2.bash
variable $v= n’est pas vide

Le résultat n’est pas vraiment surprenant. En effet, le shell remplace la variable par son contenu c’est-à-dire la
chaı̂ne vide, ce qui fait que la condition1 -n qui teste si l’argument n’est pas la chaı̂ne vide retourne vrai dans la
mesure où il n’y a pas d’argument !

Dans le second cas, on lui passe une chaı̂ne dans laquelle la valeur de la variable $v est contenue. Cette fois,
nous avons bien la chaı̂ne vide, c’est-à-dire qu’il existe réellement un argument sur lequel le test peut être effectué.

Autrement dit l’expression [ -n ], comme [ -n “toto” ] retourne vrai alors que [ -n “” ] retourne faux.

1.1 Exemples complémentaires


Le fait que le shell interprète le contenu des variables apparaı̂t clairement dans l’exemple ci-dessous :

# !/bin/bash
LS=”ls”
PARAMS=” -al”
$LS $PARAMS $HOME

Tout se passe en deux temps, dans un premier temps, les variables sont remplacées par leur contenu, et dans un
second temps, la ligne est interprétée comme une ligne de commande.

Protection du nom de la variable. Il existe certaines situations pour lesquelles on est obligé de coller le nom de
la variable avec d’autres chaı̂nes de caractères ce qui pose des problèmes d’interprétation. Exemple :

# !/bin/bash
a=”a”
ab=”abbb”
abbb=”non, ce n’est pas là”
echo ”$a bbb même chose que $ab”
echo ”$abbb même chose que $ab”
echo ”$abbb même chose que $ab”
echo

Sur la sortie standard, on récupère :

a bbb même chose que abbb


non, ce n’est pas la même chose que abbb
abbb même chose que abbb
1 cf Section 4

5
2 Arguments ligne de commande
Pour certains scripts, il est essentiel de travailler avec des paramètres, et de pouvoir vérifier que le nombre de
paramètres correspond à l’usage que l’on attend du script. La variable qui contient cette valeur est : $#
Les valeurs des paramètres se trouvent dans $1 $2... Il existe également d’autres variables prédéfinies qui contiennent
ces arguments : $* et $@

Ces variables internes et quelques autres sont parfois appelés paramètres de position :
– $1, $2... : les arguments de la ligne de commande
– $* : les arguments de la ligne de commande vus comme une seule chaı̂ne de caractères
– $@ : les arguments de la ligne de commande vus chacun comme une chaı̂ne de caractère
– $# : nombre d’arguments suivant le nom du script invoqué
Voici un exemple de script qui permet d’afficher le nombre et le contenu des paramètres selon plusieurs
manières :

# !/bin/bash

echo
if [ ”$#” -eq 0 ] ;
then
echo ”il faudrait que vous saisissiez au moins un paramètre”
exit 1
fi
echo ”Vous avez saisi $# paramètres”
echo ”dont voici les valeurs :”
echo ” le premier argument est $1”
echo ”Voici l’ensemble des paramètres : ”
for arg in ”$*”
do
echo ” selon \$* : $arg”
done
echo
index=1
for arg in ”$@”
do
echo ” selon \$@ paramètre numéro $index : $arg”
let ”index+=1”
done
echo

Autres paramètres spéciaux :

– $ ! : indique le numéro du dernier processus lancé en tâche de fond.


– $$ : indique le numéro du processus du script lui même.
– $ ? : valeur de retour de la dernière commande évaluée.
– $ : dernier argument de la dernière commande lancée.

3 Evaluation d’expressions arithmétiques


3.1 Commandes et opérateurs
Il existe trois principales commandes pour évaluer des expressions arithmétiques :

– let
– ((...))

6
– $((...))
Toutes les opérations arithmétiques utilisent des entiers longs. Lorqu’elles sont utilisées à l’intérieur de ces
commandes, les variables ne nécessitent pas de commencer par $ pour l’accès à leur contenu.
Attention : ne pas confondre $((...)) qui permet d’évaluer une expression arithmétique avec $(...) qui est une com-
mande de substitution (remplace l’ancien ‘...‘)

Les principaux opérateurs sont classiques :


– +-
– / division entière, % modulo (reste de la division entière)
– * (multiplication) ** (puissance)
– && (et logique) —— (ou logique)
– = += -= *= /= %= (opérateurs d’affectation)

3.2 Exemple

# !/bin/bash

a=12
b=20
c=3

let ”d=a+b”
((e=b/a))
f=$((b**c))

echo ”addition : $a + $b = $d”


echo ”division entière : $b / $a = $e”
echo ”puissance : $b ** $c = $f”
echo ”reste de division entière : $b % $c = $((b%c))”

3.3 Commande expr


Il est également possible d’utiliser la commande expr pour évaluer une expression. man expr pour une explica-
tion en détail.

4 Structures de contrôle conditionnelles


4.1 Syntaxe
Les structures de contrôle conditionnelles et itératives sont communes à tous les langages de programmation,
mais leur syntaxe diffère. En bash :

if condition ;
then
instruction 1
instruction 2
fi

ou

7
if condition ;
then
instruction 1
instruction 2
else
instruction 3
instruction 4
fi

ou

if condition ;
then
instruction 1
instruction 2
elif condition2 ;
then
instruction 3
instruction 4
else
instruction 5
instruction 6
fi

4.2 Exemple

# !/bin/bash if [ $# -eq 0 ] ;
then
echo ”pas de paramètres”
elif [ $# -eq 1 ] ;
then
echo ”1 paramètre”
elif [ $# -eq 2 ] ;
then
echo ”2 paramètres”
else
echo ”plus de deux paramètres”
fi

5 Opérateurs de comparaison
La commande utilisée dans les expressions conditionnelle est la commande test, dont la syntaxe est : test
opérande1 opérateur opérande2, pour les opérateurs binaires (pour les opérateurs unaires, l’opérande1 est omis).
Mais il en existe une autre syntaxe : [ opérande1 opérateur opérande2 ]

Attention : les espaces entre les crochets et les opérandes et autour de l’opérateur sont requis

Les différents opérateurs de comparaisons :

8
– if [ $a -eq $b ] teste l’égalité des entiers contenues dans les variables $a et $b. Si tel est le cas, renvoie vrai
et faux sinon.
– if [ $a -neq $b ] teste si les deux opérandes entiers sont différents
– if [ $a = $b ] teste si les deux opérandes chaı̂nes de caractères sont égaux
– if [ $a != $b ] teste si les deux opérandes chaı̂nes de caractères sont différents
– if [ $a -lt $b ] teste si $a est strictement plus petit que $b (ce sont des entiers)
– if [ $a -ge $b ] teste si $a est supérieur ou égal à $b (ce sont des entiers)
– if [ -n $a ] teste si $a n’est pas de longueur nulle
– if [ -z $a ] teste si $a est de longueur nulle
– if [ -e $HOME/.bashrc ] teste si le fichier $HOME/.bashrc existe
– if [ -L truc ] teste si truc est un lien symbolique
– if [ -f fic ] teste si fic est un fichier régulier
– if [ -d dir ] teste si dir est un répertoire

# !/bin/bash
if [ $# -lt 3 ] ;
then
echo ”il faut 3 paramètres”
exit
fi
if [ -n ”$1” ] ;
then
echo ”la chaine \$1=$1 est non vide”
else
echo ”la chaı̂ne \$1= est vide”
fi
if [ $2 -ge $3 ] ;
then
echo ”$2 est supérieur ou égal à $3”
else
echo ”$2 est inférieur strictement à $3”
fi

# !/bin/bash
if [ -e ”$1” ] ;
then
echo ”le fichier $1 existe”
if [ -L ”$1” ] ;
then
echo ”c’est un lien symbolique”
elif [ -f ”$1” ] ;
then
echo ”c’est un fichier régulier”
elif [ -d ”$1” ] ;
echo “c’est un répertoire”
fi
else
echo ”$1 n’existe pas”
fi

9
6 Structures de contrôle itératives
Il existe deux formes de constructions itératives, les boucles for et les boucles while. Les premières permettent
d’itérer sur un ensemble de valeurs ou d’items précis alors que les secondes itèrent sur une condition.

6.1 Boucles for


6.1.1 Syntaxe

forvariable in ensemble de valeurs


do
instruction 1
instruction 2
done

Par défaut, le shell considère le symbole ’machin*’ comme l’ensemble des fichiers dont le nom correspond à
l’expression machin suivi de n’importe quelle suite d’autres symboles. Ainsi * seul correspond à l’ensemble des
fichiers situés dans le répertoire de travail.

6.1.2 Exemple

# !/bin/bash

bfr=”bonjour”
bit=”buon giorno”
beng=”good morning”

for bonjour in $bfr $bit $beng


do
echo ”bonjour $bonjour”
done
echo
for bonjour in ”$bfr” ”$bit” ”$beng”
do
echo ”bonjour $bonjour”
done

10
# !/bin/bash

nbfichiers=0
nbrep=0

for fichier in *
do
if [ -f $fichier ] ;
then
let ”nbfichiers+=1”
elif [ -d $fichier ] ;
then
let ”nbrep+=1”
fi
done
echo ”le répertoire courant $PWD contient :”
echo ”$nbfichiers fichiers et ”
echo ”$nbrep répertoires”
echo

6.2 Boucles while


6.2.1 Syntaxe

while[ opérande1 opérateur opérande2 ]


do
instruction 1
instruction 2
done

6.2.2 Exemple

# !/bin/bash
X=0
while [ $X -le 20 ]
do
echo $X
X=$((X+1))
done

7 Expressions régulières
Une expression régulière peut être considérée comme un modèle de motifs. Il existe des caractères à la signifi-
cation spéciale : ’[’, ’.’, ’*’, ’ˆ’, ’$’ et ’\’.
– Le crochet ouvrant ’[’ est l’indicateur de début de la définition d’un ensemble de caractères.
→ [abcABC] (les caractères a, b, c, A, B, C), [0-9] (les chiffres de 0 à 9 inclus), [ :space :] (les caractères
d’espacement).
– Le point ’.’ désigne un caractère quelconque sauf le caractère de fin de ligne.

11
→ ab.cd désigne toutes les chaı̂nes qui contiennent une chaı̂ne de 5 caractères qui commence par ab et se finit
par cd
– L’étoile ’*’ indique que l’expression qui le précède peut être présente un nombre de fois quelconque dans la
chaı̂ne.
→ ab*cd correspond à toutes les chaı̂nes qui contiennent une chaı̂ne commençant par a et se finissant par cd
et contenant un nombre quelconque de b entre le a et le c, [a-z]*[0-9][0-9][A-Z] désigne toutes les chaı̂nes
formées d’un nombre quelconque de minuscules suivies par deux chiffres et une lettre majuscule.
– L’accent circonflexe ’ˆ’ désigne le début de ligne s’il est en début d’expression, ou la négation de l’ensemble
s’il est le premier caractère suivant le crochet ouvrant.
→ ˆ[0-9] toutes les chaı̂nes commençant par un chiffre, ˆ[ˆ0-9] désigne toutes les chaı̂nes ne commençant pas
par un chiffre.
– Le symbole dollar ’$’ désigne la fin de la ligne.
→ ˆ0[A-Z]*4$ désigne toutes les chaı̂nes qui commencent par le chiffre 0 suivi par un nombre quelconque de
majuscules et qui se terminent par le chiffre 4.
Autres formes d’expressions :
– a\{7\} : les chaı̂nes qui vérifient cette expression régulière doivent contenir une suite de 7 ’a’ consécutifs
– a\{7,\} au moins 7 ’a’
– a\{3,10\} au minimum 3 et au maximum 10 ’a’
– ([0-9]\{3\})[a-z]([0-9])\1\2 ce mécanisme permet de conserver en mémoire la chaı̂ne qui vérifie l’expres-
sion régulière entre parenthèses, et de la rappeler ensuite à l’aide de \numéro
→ les chaı̂nes ABCD876r48764YUET et 999a39993 vérifient l’expression régulière

8 Tableaux
8.1 Présentation
Les tableaux sont une structure de données essentielle en algorithmique. Un tableau est un ensemble de va-
riables que l’on peut accéder en lecture et en écriture à partir du même identifiant (tablo dans l’exemple ci-après),
en spécifiant une position dans le tableau.

Exemple :

position 1 2 3 4 5
nom de la variable tablo[1] tablo[2] tablo[3] tablo[4] tablo[5]
valeur 23 78 bonjour “il fait beau” -78.7654

8.2 Initialisation

# !/bin/bash

#————————
echo ”initialisation”

index=0
while [ $index -le 9 ]
do
tab[$index]=$RANDOM
let ”index++”
done

Cet exemple montre comment il est possible de construire un tableau de 10 entiers qui sont tirés aléatoirement
(entre 0 et 32767). La variable $RANDOM est une variable prédéfinie.
Il est possible d’initialiser une tableau directement :

12
# !/bin/bash

#————————
echo ”initialisation”

tab=($RANDOM 12 $RANDOM milieu 56 “il fait beau aujourd’hui”)

8.3 Lecture des éléments d’un tableau

# !/bin/bash

tab=($RANDOM 12 $RANDOM milieu 56 “il fait beau aujourd’hui”)


#————————
echo ”contenu du tableau”

index=0
while [ $index -le 5 ]
do
echo ”$index : $tab[$index]”
let ”index=index+1”
done

Le nom de l’élément du tableau doit impérativement être entre accolade, dans le cas contraire, $tab est considéré
comme une variable et [$index] comme une chaı̂ne formée d’un crochet ouvrant, suivi d’une variable, suivie d’un
crochet fermant.
Les sorties de cet exemple sont les suivantes :

contenu du tableau
0 : 11208
1 : 12
2 : 9540
3 : milieu
4 : 12052
5 : il fait beau aujourd’hui

8.4 Taille d’un tableau


Il peut être intéressant de connaı̂tre le nombre d’éléments d’un tableau. Si l’identifiant de notre tableau est
tablo alors son nombre d’éléments est égal à : $#tablo[*]

Exemple :

13
# !/bin/bash

index=0

echo ”remplissage du tableau”


echo

nb=$RANDOM
while [ $((nb%2)) -eq 0 ]
do
tablo[$index]=$nb
let ”index=index+1”
nb=$RANDOM
done

echo ”taille du tableau : $#tablo[*]”


echo
echo ”contenu du tableau :”
echo

index=0
while [ $index -lt $#tablo[*] ]
do
echo $index $tablo[$index]
let ”index=index+1”
done

Ce script construit un tableau dont le nombre d’éléments n’est pas connu, mais dont tous les éléments sont
pairs (c’est-à-dire que le reste de la division par 2 vaut 0).
Exemple de sorties à l’écran :

remplissage du tableau

taille du tableau : 4

contenu du tableau :

0 28282
1 2254
2 26758
3 19670

9 Lecture entrée standard

14

Vous aimerez peut-être aussi