Le Shell est un langage-clef de Unix puisqu'utilisé lui-même dans les commandes. Par exemple, le ls dont le fonctionnement a été cité dans la rubrique présentation de Unix est une commande shell.
Le shell, sh, de Bourne est apparu en 1969. Depuis, il a subit toutes sortes de mutations, d'améliorations plus ou moins discutables comme le CShell. En 1985 le Kornshell, ksh, s'impose jusqu'en 1990 où le bash, (Bourne again shell) vient s'imposer. Le bash qui est actuellement le logiciel qu'on utilise fait partie du projet GNU. GNU signifiant : Gnu is Not Unix (Le GNU n'est pas Unix).
Mais que signifie G.N.U.?
Nous venons de le dire : GNU's Not Unix !!
Il vaut mieux laisser tomber et se concentrer sur le bash.
L'invite d'Unix, le prompt, est symbolisée par "?".
Quelques commandes :
?echo "blablabla"
affichera
?blablabla
?cat bof
echo "blablabla"
Va créer un fichier dont le nom sera bof et qui aura pour contenu echo "blablabla"
Ainsi, après avoir rendu le fichier exécutable, si on tape
?bof
l'affichage sera
?blablabla
?rm core
efface le fichier core
La redirection
exemple :
?ls>monls
créé un fichier monls qui a pour contenu ls.
Si le fichier monls existe déjà, im sera détruit et remplacé.
?ls>>monls
Ajoute ls au fichier monls, sans le remplacer.
Inversement, on peut utiliser <
?ls>>monls ó ?monls<<ls
Le pipe |
exemple :
?cat monfichier>Aimprimer
?Lpr Aimprimer
équivaut à
?cat monfichier|lpr
Le pipe permet donc de faire des commandes de commandes.
Ainsi.
?cat monfich|grep total|Lpr
va imprimer (Lpr) les lignes où se trouvent le mot total (grep total) dans le contenu du fichier "monfich" (cat monfich)
?ls -al|grep x|grep -v dr|Lpr
affiche la liste des fichiers avec les détails (ls -al) sélectionne les lignes où il y a x, c'est à dire les exécutables, (grep x), pour ensuite les prendre tout sauf celles où il y a dr, c'est-à-dire toutes, sauf les directories,(grep -v dr) et enfin les imprimer (Lpr)
Le dollar $
A présent, créons des fichiers à l'aide d'éditeurs de fichiers comme emacs=85
Le $1 prend le terme qui vient juste à droite après l'exécution du fichier.
Par exemple, si je fais un fichier foo, qui contient :
echo $1
A l'invite, le résultat sera :
?foo salut
affiche
?salut
De même, si foo contient :
a=$1
b='expr $a + 5'
echo $b
A l'invite
?foo 8
stocke la valeur 8 dans la variable a, stocke dans la variable b la valeur 5 + $a, c'est-à-dire 5 + la valeur de a, donc 8 + 5, grosso-modo, 13. Enfin, affiche la valeur de b, c'est-à-dire 13. Donc le résultat est :
?13
le $# est le nombre de paramètres sur la ligne
$*, correspond à la ligne entière.
Créons le fichier bourre, ayant pour contenu :
echo $0
echo $1
echo $2
echo $3
echo $*
echo "c'etait la ligne"
echo "avec"
echo $#
echo "elements"
A l'invite, on tape :
?bourre je suis a la bourre
Affiche donc :
?bourre
je
suis
a
je suis a la bourre
c'etait la ligne
avec
5
elements
le shift est une commande qui décale les termes d'une ligne vers la gauche.
Exemple
echo $0
echo $1
echo $2
équivaut à
echo $0
shift
echo $1
shift
echo $2
Le "si a est b, alors faire c, sinon faire d"
En shell :
if test -f toto
then
rm toto
else
echo fichiervide>toto
fi
Si le fichier toto existe,
Alors
Détruire toto
autrement
créer toto en mettant fichiervide dedans
fin du si.
Un autre exemple :
If test $# -ge 9
then
shift
echo $9
else
echo $9
fi
Si j'ai plus de 9 termes sur la ligne
Alors
Décaler les termes d'une place vers la droite
Afficher le 9ème
Sinon
Afficher le 9ème
Fin du si
Les boucles (ça se gâte)
Il existe deux types de boucles : la récursivité, et l'itérativité.
L'itérativité est plus compliquée à mettre en place que la récursivité. Pour schématiser, dans l'itérativité, c'est l'étudiant qui travaille, alors que dans la récursivité, c'est la machine.
Prenons les factorielles . 5!=5 x 4 x 3 x 2 x 1, 1!
De même n!=1 x 2 x 3 x =85 x n
On a, également n!=(n - 1) x n
En récursivité : on créé un fichier fac :
If test $# -eq 1
then
if test $1 -gt 1
then
a='expr $1 - 1'
b='expr $1 \* fac $a'
echo $b
else
echo 1
fi
echo "j'ai autre chose a faire"
fi
Si je n'ai qu'un argument sur la ligne
Alors
Si le premier terme est plus grand que 1
Alors
Je stocke le premier terme - 1 dans la variable a
Je stocke le résultat de (fac de la valeur de a) dans b
J'affiche la valeur de b
Sinon
J'affiche 1
Sinon
J'affiche "j'ai autre chose a faire"
Donc, si la ligne ne contient qu'un seul terme, je créé une boucle en le décrémentant jusqu'à ce qu'il atteigne 1, pour multiplier chaque tour de boucle avec le résultat du précédent.
Avec l'itérativité :
number = $1
index='expr $number - 1'
while test $index -ge 1
do
number='expr $number \* $index'
index='expr $index - 1'
done
echo la factorielle de $1 est $number
Je stocke le premier terme dans la variable appelée number
Je stocke la valeur de number - 1 dans la variable index
Tant que la valeur de number est plus grande que 1
Je fais
Je stocke la valeur de number multipliée par la valeur de index dans la variable number
Je stocke la valeur de index -1 dans la variable index
J'ai fini
J'affiche "la factorielle du premier terme est la valeur de la variable number.
C'est le même principe que la récursivité, mais ici, la boucle est créée par le while, le 'tant que'.