Bap: Tests et calcul arithmétique en shell
This commit is contained in:
parent
65e2de4b07
commit
96a1692382
4 changed files with 470 additions and 5 deletions
|
@ -90,6 +90,18 @@ Vous venez de terminer ce programme, et vous
|
|||
fonctionne comme vous le voulez.
|
||||
</p>
|
||||
|
||||
<div class="encadre">
|
||||
Soyons honnêtes : cet exemple est un peu tiré par les cheveux, car
|
||||
il existe une commande très simple pour faire cela :
|
||||
<pre>
|
||||
rm -i *.aux *.log
|
||||
</pre>
|
||||
|
||||
Mais ici, cet exemple <em>à la limite</em> est là pour illustrer d'une
|
||||
façon simple l'intérêt des fonctions... Disons alors que cet exemple
|
||||
permet de donner une version francisée de la commande
|
||||
<code>rm -i *.aux *.log</code> !
|
||||
</div>
|
||||
|
||||
<h3>Problèmes des programmes sans fonction</h3>
|
||||
|
||||
|
@ -131,7 +143,7 @@ L'utilisation des fonctions se fait en deux moments :
|
|||
|
||||
<ol>
|
||||
<li> d'abord, il faut <strong>définir la fonction</strong> : vous
|
||||
décrivez quelle série de commandes il faudra exécuter lrosque l'on
|
||||
décrivez quelle série de commandes il faudra exécuter lorsque l'on
|
||||
appellera la fonction ;</li>
|
||||
|
||||
<li> ensuite, il faut <strong>appeler la fonction</strong> à chaque
|
||||
|
@ -405,7 +417,7 @@ complexes.
|
|||
|
||||
<div class="metainformation">
|
||||
Auteur : Baptiste Mélès.
|
||||
Dernière modification le <date value="$Date: 2005-09-07 09:02:15 $" />.
|
||||
Dernière modification le <date value="$Date: 2005-09-07 10:03:49 $" />.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -80,7 +80,10 @@ redirection</a> ;</li>
|
|||
|
||||
<li> <a href="test.html">test et calcul arithmétique</a> ;</li>
|
||||
|
||||
<li> <a href="boucle.html">boucles et structures de contrôle</a>.</li>
|
||||
<li> <a href="boucle.html">boucles et structures de
|
||||
contrôle</a> ;</li>
|
||||
|
||||
<li> <a href="fonction.html">définir et appeler des fonctions</a>.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
@ -88,7 +91,7 @@ redirection</a> ;</li>
|
|||
Basé sur un polycopié de Roberto Di Cosmo, Xavier Leroy et Damien
|
||||
Doligez.
|
||||
Modifications : Nicolas George, Baptiste Mélès.
|
||||
Dernière modification le <date value="$Date: 2005-07-05 07:18:06 $"
|
||||
Dernière modification le <date value="$Date: 2005-09-07 10:03:53 $"
|
||||
/>.
|
||||
</div>
|
||||
|
||||
|
|
|
@ -604,10 +604,39 @@ read
|
|||
echo "Les pattes, surtout la gauche."
|
||||
</pre>
|
||||
|
||||
<h2>Poursuivre l'apprentissage de la programmation shell</h2>
|
||||
|
||||
<p>
|
||||
Vous connaissez maintenant les bases de la programmation en shell. Vous
|
||||
avza déjà de quoi écrire de nombreux scripts qui peuvent vous faciliter
|
||||
la vie de tous les jours. Pour cela, lorsque vous ressentez un besoin,
|
||||
ne vous demandez pas si vous avez les connaissances requises pour écrire
|
||||
un programme donné, mais plutôt <em>comment, à partir de vos
|
||||
connaissances actuelles, vous pourriez le réaliser</em>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Pour poursuivre votre apprentissage, vous pouvez passer à la lecture des
|
||||
pages suivanets :
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> <a href="entreesortie.html">entrée, sortie,
|
||||
redirection</a> ;</li>
|
||||
|
||||
<li> <a href="test.html">test et calcul arithmétique</a> ;</li>
|
||||
|
||||
<li> <a href="boucle.html">boucles et structures de
|
||||
contrôle</a> ;</li>
|
||||
|
||||
<li> <a href="fonction.html">définir et appeler des fonctions</a>.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
<div class="metainformation">
|
||||
Auteur : Baptiste Mélès.
|
||||
Dernière modification le <date value="$Date: 2005-07-05 07:18:06 $" />.
|
||||
Dernière modification le <date value="$Date: 2005-09-07 10:03:54 $" />.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
|
421
unix/shell/test.tml
Normal file
421
unix/shell/test.tml
Normal file
|
@ -0,0 +1,421 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE html
|
||||
PUBLIC "-//ENS/Tuteurs//DTD TML 1//EN"
|
||||
"tuteurs://DTD/tml.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Tests</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Tests et calcul arithmétique</h1>
|
||||
|
||||
<h2>Qu'est-ce qu'un test ?</h2>
|
||||
|
||||
<p>
|
||||
<strong>Un test est une opération dont le but est d'évaluer la valeur
|
||||
d'une expression</strong>. Cette expression peut être simplement
|
||||
l'<em>existence</em> de quelque chose (par exemple, d'un fichier, ou
|
||||
bien d'une variable), ou ce peut être une <em>proposition</em>.</p>
|
||||
|
||||
<p>Concrètement, cela veut dire qu'<strong>un programme n'est pas limité
|
||||
à la possibilité de donner des ordres : il peut aussi poser des
|
||||
questions</strong>, et agir comme vous le décidez en fonction des
|
||||
réponses apportées aux questions.</p>
|
||||
|
||||
<p>Posons par exemple le principe suivant : « Si Dieu n'existe
|
||||
pas, alors tout est permis. » Nous allons ensuite tester si Dieu
|
||||
existe, et s'il n'existe pas, nous saurons que tout est permis. Autre
|
||||
exemple : posons que « si le train passe sous le tunnel avant
|
||||
que j'aie compté jusqu'à dix, alors Manek est vivant. » Je vais
|
||||
donc tester si le train passe sous le tunnel avant que j'aie compté
|
||||
jusqu'à dix, et si c'est le cas, alors c'est que Manek est vivant. C'est
|
||||
aussi simple que cela.</p>
|
||||
|
||||
<h3>Une condition</h3>
|
||||
<p>Le shell propose trois façons de réaliser un test ; ces trois
|
||||
méthodes sont équivalentes :</p>
|
||||
|
||||
<ul>
|
||||
<li> <code>test <em>expression</em></code></li>
|
||||
<li> <code>[ <em>expression</em> ]</code></li>
|
||||
<li> <code>[[ <em>expression</em> ]]</code></li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Les trois commandes suivantes reviennent donc au même :</p>
|
||||
|
||||
<pre>
|
||||
<span class="prompt">clipper ~ $</span> <strong>test -f foo</strong> || echo "Le fichier foo n'existe pas."
|
||||
Le fichier foo n'existe pas.
|
||||
<span class="prompt">clipper ~ $</span> <strong>[ -f foo ]</strong> || echo "Le fichier foo n'existe pas."
|
||||
Le fichier foo n'existe pas.
|
||||
<span class="prompt">clipper ~ $</span> <strong>[[ -f foo ]]</strong> || echo "Le fichier foo n'existe pas."
|
||||
Le fichier foo n'existe pas.
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Code de retour d'un test</h3>
|
||||
<p>Un test renvoie un <em>code de retour</em>. <strong>Un code de retour
|
||||
est un chiffre binaire (1 ou 0), qui correspond à une réponse de
|
||||
type « vrai » ou « faux »</strong>. C'est ce code de
|
||||
retour qui permet la manipulation des tests dans des structures de
|
||||
contrôle comme <code>if</code>, etc. </p>
|
||||
|
||||
<p>Par exemple, un pilote de Formule 1 utilise le programme
|
||||
suivant :</p>
|
||||
|
||||
<pre>
|
||||
while [[ "$couleur_du_feu" != "vert" ]]
|
||||
do attendre
|
||||
done
|
||||
|
||||
démarrer_en_trombe
|
||||
</pre>
|
||||
|
||||
|
||||
<h2>Les opérateurs</h2>
|
||||
|
||||
<h3>Opérateurs logiques</h3>
|
||||
|
||||
<h4>Non : l'opérateur « <code>!</code> »</h4>
|
||||
|
||||
<p><strong>L'opérateur logique « non » inverse le code de
|
||||
retour d'une commande</strong>, c'est-à-dire renvoie vrai si elle
|
||||
renvoie faux, et vice versa. </p>
|
||||
|
||||
<p>On utilise cet opérateur en précédant une condition d'un point
|
||||
d'exclamation (« ! »). </p>
|
||||
|
||||
|
||||
<h5>Comparaison de plusieurs combinaisons d'opérateurs</h5>
|
||||
|
||||
<p>Pour illustrer l'usage de cet opérateur, voici quatre cas de figure
|
||||
différents :</p>
|
||||
|
||||
<pre>
|
||||
# Premier cas
|
||||
[ <strong>-f</strong> foo ] <strong>&&</strong> echo "Le fichier foo existe."
|
||||
</pre>
|
||||
|
||||
<p class="continue">Dans l'exemple précédent, le shell teste si le
|
||||
fichier <code>foo</code> existe. Comme il n'existe pas, le code de
|
||||
retour de ce test est 0. Or, l'opérateur « && »
|
||||
n'exécute ce qui suit que si le code de retour est 1. Comme ce
|
||||
n'est pas le cas, les commandes ne sont pas exécutées.</p>
|
||||
|
||||
<pre>
|
||||
# Deuxième cas
|
||||
[ <strong>-f</strong> foo ] <strong>||</strong> echo "Le fichier foo n'existe pas."
|
||||
Le fichier foo n'existe pas.
|
||||
</pre>
|
||||
|
||||
<p class="continue">Dans cet exemple, l'opérateur n'est plus
|
||||
« && » mais « || ». Les commandes ne
|
||||
s'exécutent que si le code de retour vaut 0 ; comme c'est le cas,
|
||||
elles sont exécutées.</p>
|
||||
|
||||
<pre>
|
||||
# Troisième cas
|
||||
[ <strong>! -f</strong> foo ] <strong>&&</strong> echo "Le fichier foo n'existe pas.
|
||||
Le fichier foo n'existe pas.
|
||||
</pre>
|
||||
|
||||
<p class="continue">Ici, l'opérateur est de nouveau
|
||||
« && » ; mais contrairement aux deux exemples
|
||||
précédents, le test n'est plus <code>[ -f foo ]</code>
|
||||
mais <code>[ ! -f foo ]</code>. Par conséquent, le
|
||||
code de retour est 1, et les commandes sont exécutées.</p>
|
||||
|
||||
<pre>
|
||||
# Quatrième cas
|
||||
[ <strong>! -f</strong> foo ] <strong>||</strong> echo "Le fichier foo existe.
|
||||
</pre>
|
||||
|
||||
<p class="continue">Voici la dernière combinaison possible. Le code de
|
||||
retour est 1, mais il fallait 0 pour que les commandes soient
|
||||
exécutées. </p>
|
||||
|
||||
|
||||
|
||||
<p>Ces quatre exemples correspondent aux énoncés suivants :</p>
|
||||
|
||||
<ul>
|
||||
<li> <em>s'il est vrai que <code>foo</code> existe</em>, alors il faut
|
||||
écrire : « Le fichier foo existe. ».</li>
|
||||
|
||||
<li> <em>s'il n'est pas vrai que <code>foo</code> existe</em>, alors il
|
||||
faut écrire : « Le fichier foo n'existe pas. ».</li>
|
||||
|
||||
<li> <em>s'il est vrai que <code>foo</code> n'existe pas</em>, alors il
|
||||
faut écrire : « Le fichier foo n'existe pas. ».</li>
|
||||
|
||||
<li> <em>s'il n'est pas vrai que <code>foo</code> n'existe pas</em>,
|
||||
alors il faut écrire : « Le fichier foo existe. ».</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h5>Reformulation avec <code>if</code></h5>
|
||||
|
||||
<p>Dans un script, outre la formulation précédente, on pourra
|
||||
écrire :</p>
|
||||
|
||||
<pre>
|
||||
# Premier cas
|
||||
if [ -f foo ]
|
||||
then echo "Le fichier foo existe."
|
||||
else continue
|
||||
fi
|
||||
|
||||
# Deuxième cas
|
||||
if [ -f foo ]
|
||||
then continue
|
||||
else echo "Le fichier foo n'existe pas."
|
||||
fi
|
||||
|
||||
# Troisième cas
|
||||
if [ ! -f foo ]
|
||||
then echo "Le fichier foo n'existe pas."
|
||||
else continue
|
||||
fi
|
||||
|
||||
# Quatrième cas
|
||||
if [ ! -f foo ]
|
||||
then continue
|
||||
else echo "Le fichier foo existe."
|
||||
fi
|
||||
</pre>
|
||||
|
||||
|
||||
<h4>Et : l'opérateur « <code>-a</code> »</h4>
|
||||
<p>L'opérateur « et » renvoie 1 (vrai) si et seulement si
|
||||
les différentes conditions sont toutes réalisées ; si au moins
|
||||
l'une d'entre elles ne l'est pas, le code de retour est 0
|
||||
(faux). On note cet opérateur en insérant « -a » entre les
|
||||
différentes conditions. Exemples : </p>
|
||||
|
||||
<pre>
|
||||
touch foo # donc foo existe
|
||||
rm bar # donc bar n'existe pas
|
||||
|
||||
# [ -f foo ] = vrai si le fichier foo existe
|
||||
# [ ! -f bar ] = vrai si bar n'existe pas
|
||||
|
||||
# à n'exécuter que si foo existe ET que bar n'existe pas.
|
||||
[ -f foo <strong>-a</strong> ! -f bar ] &&
|
||||
mv foo bar
|
||||
</pre>
|
||||
|
||||
<p class="continue">Autres formulations possibles :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
test -f foo -a ! -f bar
|
||||
[ -f foo ] -a [ ! -f bar ]
|
||||
[[ -f foo && ! -f bar ]]
|
||||
</pre>
|
||||
|
||||
<p><strong>Si vous débutez, vous n'êtes pas tenu de retenir par
|
||||
cœur toutes les combinaisons possibles. Sachez simplement les
|
||||
reconnaître</strong> si vous les lisez quelque part ; et pour vos
|
||||
propres scripts, vous il vous suffit de savoir bien manipuler la syntaxe
|
||||
qui vous paraît la plus lisible.</p>
|
||||
|
||||
|
||||
<h4>Ou : l'opérateur « <code>-o</code> »</h4>
|
||||
<p>Pour réaliser la condition de l'opérateur « ou », il suffit
|
||||
qu'une seule des conditions qu'il rassemble soit vraie : </p>
|
||||
|
||||
<ul>
|
||||
<li> si <em>toutes</em> les conditions sont rassemblées, la condition
|
||||
d'ensemble l'est aussi ;</li>
|
||||
|
||||
<li> si <em>une partie seulement</em> de ces conditions est rassemblée,
|
||||
la condition d'ensemble l'est aussi ;</li>
|
||||
|
||||
<li> si <em>aucune</em> des conditions incluses n'est remplie, la
|
||||
condition d'ensemble ne l'est pas non plus.</li>
|
||||
</ul>
|
||||
|
||||
<p>Exemple :</p>
|
||||
|
||||
<pre>
|
||||
if [[ "$fichier" == "fichier_interdit" -o ! -f "$fichier" ]]
|
||||
then echo "Je ne veux pas lire $fichier ou bien il n'existe pas."
|
||||
fi
|
||||
</pre>
|
||||
|
||||
<ul>
|
||||
<li> si <code>$fichier</code> vaut
|
||||
<code>"fichier_interdit"</code>, il n'est pas lu ;</li>
|
||||
|
||||
<li> si <code>$fichier</code> n'existe pas, il n'est pas lu ;</li>
|
||||
|
||||
<li> si <code>$fichier</code> vaut
|
||||
<code>"fichier_interdit"</code> et qu'en plus il n'existe pas,
|
||||
il n'est pas lu ;</li>
|
||||
|
||||
<li> si <code>$fichier</code> ne vaut pas
|
||||
<code>"fichier_interdit"</code> et qu'il existe bien, il est
|
||||
lu.</li> </ul>
|
||||
|
||||
<h3>Opérateurs arithmétiques</h3>
|
||||
|
||||
<p>
|
||||
Le shell permet d'opérer des calculs arithmétiques, même s'il est moins
|
||||
puissant que d'autres langages (Perl, Scheme, C, etc.) pour cela.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Les opérateurs sont les suivants :
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> <code>-eq</code> (<i>equal</i>) : « égal à » (signe
|
||||
« = ») ;</li>
|
||||
|
||||
<li> <code>-ne</code> (<i>not equal</i>) : « différent
|
||||
de » (signe « ≠ ») ;</li>
|
||||
|
||||
<li> <code>-gt</code> (<i>greater than</i>) : « strictement
|
||||
supérieur à » (signe « > ») ;</li>
|
||||
|
||||
<li> <code>-lt</code> (<i>lesser than</i>) : « strictement
|
||||
inférieur à » (signe « < ») ;</li>
|
||||
|
||||
<li> <code>-ge</code> (<i>greater or equal</i>) : « supérieur
|
||||
ou égal à » (signe « ≥ ») ;</li>
|
||||
|
||||
<li> <code>-le</code> (<i>lesser or equal</i>) : « inférieur
|
||||
ou égal à » (signe « ≤ ») ;</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
On utilise ces opérateurs entre deux nombres ou variables
|
||||
numériques. Par exemple :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
#!/bin/sh
|
||||
if test 2 -lt 3
|
||||
then echo "C'est normal."
|
||||
fi
|
||||
|
||||
if test 2 -gt 3
|
||||
then echo "C'est absurde."
|
||||
fi
|
||||
|
||||
petit=2
|
||||
grand=3
|
||||
|
||||
if test $petit -ne 3
|
||||
then echo "C'est normal."
|
||||
fi
|
||||
|
||||
if test 2 -eq $grand
|
||||
then echo "C'est absurde."
|
||||
fi
|
||||
</pre>
|
||||
|
||||
<p class="continue">
|
||||
Si vous exécutez ce programme, vous obtenez :
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
C'est normal.
|
||||
C'est normal.
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Opérateurs sur les fichiers</h3>
|
||||
|
||||
<p>
|
||||
Une grande partie de la puissance du shell se déploie dans sa faculté de
|
||||
manipuler des fichiers.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Les principaux opérateurs disponibles sont :
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li> nature du fichier :
|
||||
<ul>
|
||||
<li> <code>-e</code> (<i>exists</i>) : vérifie l'existence d'un
|
||||
fichier ;</li>
|
||||
|
||||
<li> <code>-f</code> (<i>file</i>) : vérifie l'existence d'un
|
||||
fichier, et le fait qu'il s'agisse bien d'un fichier au sens
|
||||
strict ;</li>
|
||||
|
||||
<li> <code>-d</code> (<i>directory</i>) : vérifie l'existence d'un
|
||||
répertoire ;</li>
|
||||
|
||||
<li> <code>-L</code> (<i>link</i>) : vérifie si le fichier est un
|
||||
lien symbolique ;</li>
|
||||
|
||||
</ul></li>
|
||||
|
||||
<li>attributs du fichier :
|
||||
<ul>
|
||||
<li> <code>-s</code> (<i>size</i>) : vérifie qu'un fichier n'est
|
||||
pas vide ;</li>
|
||||
</ul></li>
|
||||
|
||||
<li>droits sur le fichier :
|
||||
<ul>
|
||||
<li> <code>-r</code> (<i>readable</i>) : vérifie si un fichier peut
|
||||
être lu ;</li>
|
||||
|
||||
<li> <code>-w</code> (<i>writable</i>) : vérifie si un fichier peut
|
||||
être écrit ou modifié ;</li>
|
||||
|
||||
<li> <code>-x</code> (<i>writable</i>) : vérifie si un fichier peut
|
||||
être exécuté ;</li>
|
||||
</ul></li>
|
||||
|
||||
<li>comparaison de fichiers :
|
||||
<ul>
|
||||
<li> <code>-nt</code> (<i>newer than</i>) : vérifie si un fichier
|
||||
est plus récent qu'un autre ;</li>
|
||||
|
||||
<li> <code>-ot</code> (<i>older than</i>) : vérifie si un fichier
|
||||
est plus ancien qu'un autre.</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p>Exemple :</p>
|
||||
|
||||
<pre>
|
||||
#!/bin/sh
|
||||
|
||||
if test -e ~/.emacs
|
||||
then echo "~/.emacs existe."
|
||||
else echo "~/.emacs n'existe pas."
|
||||
fi
|
||||
|
||||
if test -d ~/.emacs
|
||||
then echo "~/.emacs est un répertoire."
|
||||
else echo "~/.emacs n'est pas un répertoire."
|
||||
fi
|
||||
|
||||
if test -f ~/.emacs
|
||||
then echo "~/.emacs est un fichier."
|
||||
else echo "~/.emacs n'est pas un fichier."
|
||||
fi
|
||||
|
||||
if test ~/.vimrc -nt ~/.emacs
|
||||
then "~/.vimrc est plus récent que ~/.emacs."
|
||||
fi
|
||||
</pre>
|
||||
|
||||
|
||||
<div class="metainformation">
|
||||
Auteur : Baptiste Mélès.
|
||||
Dernière modification le <date value="$Date: 2005-09-07 10:03:55 $" />.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue