Un guide de bash (en pdf) pour les TP de réseaux.

Transcription

Un guide de bash (en pdf) pour les TP de réseaux.
Petit aide-mémoire de programmation shell (bash)
Frédéric Guinand
IUT du Havre
1
Table des matières
1
Variables
1.1 Un petit exemple . . . . . . . . .
1.2 Variables internes . . . . . . . . .
1.3 Variables définies par l’utilisateur
1.4 Utilisation des quotes . . . . . . .
1.5 Exemples complémentaires . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
3
3
3
4
5
2
Arguments ligne de commande
6
3
Evaluation d’expressions arithmétiques
3.1 Commandes et opérateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3 Commande expr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6
6
7
7
4
Structures de contrôle conditionnelles
4.1 Syntaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
7
8
5
Opérateurs de comparaison
8
6
Structures de contrôle itératives
6.1 Boucles for . . . . . . . . .
6.1.1 Syntaxe . . . . . . .
6.1.2 Exemple . . . . . .
6.2 Boucles while . . . . . . . .
6.2.1 Syntaxe . . . . . . .
6.2.2 Exemple . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
10
10
10
10
11
11
11
7
Expressions régulières
11
8
Tableaux
8.1 Présentation . . . . . . . . . . . .
8.2 Initialisation . . . . . . . . . . . .
8.3 Lecture des éléments d’un tableau
8.4 Taille d’un tableau . . . . . . . .
12
12
12
13
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.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.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
3
– $REPLY
– $SECONDS
– paramètres de position : voir Section 2.
1.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 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, plusieurs solutions
existent.
# !/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‘.
4
# !/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.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 permettent 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 apparamment très proches (ils ne diffèrent que par l’utilisation de quotes dans le
test) :
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 condition 1 -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. cf Section 4
5
1.5
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
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
6
– $# : 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 :
–
–
–
–
3
$ ! : 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.
Evaluation d’expressions arithmétiques
3.1
Commandes et opérateurs
Il existe trois principales commandes pour évaluer des expressions arithmétiques :
– let
– ((...))
– $((...))
7
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 commande 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 explication en détail.
4
4.1
Structures de contrôle conditionnelles
Syntaxe
Les structures de contrôle conditionnelles et itératives sont communes à tous les langages
de programmation, mais leur syntaxe diffère. En bash :
8
if condition ;
then
instruction 1
instruction 2
fi
ou
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
9
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 :
– 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 -ne $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
10
# !/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
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.
11
6.1
6.1.1
Boucles for
Syntaxe
for variable 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
for i in {12..23} ; do echo $i ; done
# !/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
12
# !/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
6.2.1
Boucles while
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
13
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 signification 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.
→ 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]*[09][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’expression 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
8.1
Tableaux
Présentation
Les tableaux sont une structure de données essentielle en algorithmique. Un tableau est un
ensemble de variables 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
nom de la variable tablo[1]
valeur
23
2
tablo[2]
78
3
tablo[3]
bonjour
14
4
tablo[4]
“il fait beau”
5
tablo[5]
-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 :
# !/bin/bash
#————————
echo ”initialisation”
tab=($RANDOM 12 $RANDOM milieu 56 “il fait beau aujourd’hui”)
15
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 :
16
# !/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
1
2
3
9
28282
2254
26758
19670
Lecture entrée standard
17

Documents pareils