422 lines
12 KiB
Text
422 lines
12 KiB
Text
|
<?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<68>tique</h1>
|
|||
|
|
|||
|
<h2>Qu'est-ce qu'un test ?</h2>
|
|||
|
|
|||
|
<p>
|
|||
|
<strong>Un test est une op<6F>ration dont le but est d'<27>valuer la valeur
|
|||
|
d'une expression</strong>. Cette expression peut <20>tre simplement
|
|||
|
l'<em>existence</em> de quelque chose (par exemple, d'un fichier, ou
|
|||
|
bien d'une variable), ou ce peut <20>tre une <em>proposition</em>.</p>
|
|||
|
|
|||
|
<p>Concr<63>tement, cela veut dire qu'<strong>un programme n'est pas limit<69>
|
|||
|
<EFBFBD> la possibilit<69> de donner des ordres : il peut aussi poser des
|
|||
|
questions</strong>, et agir comme vous le d<>cidez en fonction des
|
|||
|
r<EFBFBD>ponses apport<72>es aux questions.</p>
|
|||
|
|
|||
|
<p>Posons par exemple le principe suivant : <20> Si Dieu n'existe
|
|||
|
pas, alors tout est permis. <3B> Nous allons ensuite tester si Dieu
|
|||
|
existe, et s'il n'existe pas, nous saurons que tout est permis. Autre
|
|||
|
exemple : posons que <20> si le train passe sous le tunnel avant
|
|||
|
que j'aie compt<70> jusqu'<27> dix, alors Manek est vivant. <3B> Je vais
|
|||
|
donc tester si le train passe sous le tunnel avant que j'aie compt<70>
|
|||
|
jusqu'<27> 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<66>ons de r<>aliser un test ; ces trois
|
|||
|
m<EFBFBD>thodes sont <20>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 <20> une r<>ponse de
|
|||
|
type <20> vrai <3B> ou <20> faux <3B></strong>. C'est ce code de
|
|||
|
retour qui permet la manipulation des tests dans des structures de
|
|||
|
contr<EFBFBD>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<EFBFBD>marrer_en_trombe
|
|||
|
</pre>
|
|||
|
|
|||
|
|
|||
|
<h2>Les op<6F>rateurs</h2>
|
|||
|
|
|||
|
<h3>Op<4F>rateurs logiques</h3>
|
|||
|
|
|||
|
<h4>Non : l'op<6F>rateur <20> <code>!</code> <3B></h4>
|
|||
|
|
|||
|
<p><strong>L'op<6F>rateur logique <20> non <3B> inverse le code de
|
|||
|
retour d'une commande</strong>, c'est-<2D>-dire renvoie vrai si elle
|
|||
|
renvoie faux, et vice versa. </p>
|
|||
|
|
|||
|
<p>On utilise cet op<6F>rateur en pr<70>c<EFBFBD>dant une condition d'un point
|
|||
|
d'exclamation (<28> ! <3B>). </p>
|
|||
|
|
|||
|
|
|||
|
<h5>Comparaison de plusieurs combinaisons d'op<6F>rateurs</h5>
|
|||
|
|
|||
|
<p>Pour illustrer l'usage de cet op<6F>rateur, voici quatre cas de figure
|
|||
|
diff<EFBFBD>rents :</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
# Premier cas
|
|||
|
[ <strong>-f</strong> foo ] <strong>&&</strong> echo "Le fichier foo existe."
|
|||
|
</pre>
|
|||
|
|
|||
|
<p class="continue">Dans l'exemple pr<70>c<EFBFBD>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<6F>rateur <20> && <3B>
|
|||
|
n'ex<65>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<65>cut<75>es.</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
# Deuxi<78>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<6F>rateur n'est plus
|
|||
|
<EFBFBD> && <3B> mais <20> || <3B>. Les commandes ne
|
|||
|
s'ex<65>cutent que si le code de retour vaut 0 ; comme c'est le cas,
|
|||
|
elles sont ex<65>cut<75>es.</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
# Troisi<73>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<6F>rateur est de nouveau
|
|||
|
<EFBFBD> && <3B> ; mais contrairement aux deux exemples
|
|||
|
pr<EFBFBD>c<EFBFBD>dents, le test n'est plus <code>[ -f foo ]</code>
|
|||
|
mais <code>[ ! -f foo ]</code>. Par cons<6E>quent, le
|
|||
|
code de retour est 1, et les commandes sont ex<65>cut<75>es.</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
# Quatri<72>me cas
|
|||
|
[ <strong>! -f</strong> foo ] <strong>||</strong> echo "Le fichier foo existe.
|
|||
|
</pre>
|
|||
|
|
|||
|
<p class="continue">Voici la derni<6E>re combinaison possible. Le code de
|
|||
|
retour est 1, mais il fallait 0 pour que les commandes soient
|
|||
|
ex<EFBFBD>cut<EFBFBD>es. </p>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<p>Ces quatre exemples correspondent aux <20>nonc<6E>s suivants :</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li> <em>s'il est vrai que <code>foo</code> existe</em>, alors il faut
|
|||
|
<EFBFBD>crire : <20> Le fichier foo existe. <3B>.</li>
|
|||
|
|
|||
|
<li> <em>s'il n'est pas vrai que <code>foo</code> existe</em>, alors il
|
|||
|
faut <20>crire : <20> Le fichier foo n'existe pas. <3B>.</li>
|
|||
|
|
|||
|
<li> <em>s'il est vrai que <code>foo</code> n'existe pas</em>, alors il
|
|||
|
faut <20>crire : <20> Le fichier foo n'existe pas. <3B>.</li>
|
|||
|
|
|||
|
<li> <em>s'il n'est pas vrai que <code>foo</code> n'existe pas</em>,
|
|||
|
alors il faut <20>crire : <20> Le fichier foo existe. <3B>.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
|
|||
|
<h5>Reformulation avec <code>if</code></h5>
|
|||
|
|
|||
|
<p>Dans un script, outre la formulation pr<70>c<EFBFBD>dente, on pourra
|
|||
|
<EFBFBD>crire :</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
# Premier cas
|
|||
|
if [ -f foo ]
|
|||
|
then echo "Le fichier foo existe."
|
|||
|
else continue
|
|||
|
fi
|
|||
|
|
|||
|
# Deuxi<78>me cas
|
|||
|
if [ -f foo ]
|
|||
|
then continue
|
|||
|
else echo "Le fichier foo n'existe pas."
|
|||
|
fi
|
|||
|
|
|||
|
# Troisi<73>me cas
|
|||
|
if [ ! -f foo ]
|
|||
|
then echo "Le fichier foo n'existe pas."
|
|||
|
else continue
|
|||
|
fi
|
|||
|
|
|||
|
# Quatri<72>me cas
|
|||
|
if [ ! -f foo ]
|
|||
|
then continue
|
|||
|
else echo "Le fichier foo existe."
|
|||
|
fi
|
|||
|
</pre>
|
|||
|
|
|||
|
|
|||
|
<h4>Et : l'op<6F>rateur <20> <code>-a</code> <3B></h4>
|
|||
|
<p>L'op<6F>rateur <20> et <3B> renvoie 1 (vrai) si et seulement si
|
|||
|
les diff<66>rentes conditions sont toutes r<>alis<69>es ; si au moins
|
|||
|
l'une d'entre elles ne l'est pas, le code de retour est 0
|
|||
|
(faux). On note cet op<6F>rateur en ins<6E>rant <20> -a <3B> entre les
|
|||
|
diff<EFBFBD>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
|
|||
|
|
|||
|
# <20> n'ex<65>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'<27>tes pas tenu de retenir par
|
|||
|
cœur toutes les combinaisons possibles. Sachez simplement les
|
|||
|
reconna<EFBFBD>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<72>t la plus lisible.</p>
|
|||
|
|
|||
|
|
|||
|
<h4>Ou : l'op<6F>rateur <20> <code>-o</code> <3B></h4>
|
|||
|
<p>Pour r<>aliser la condition de l'op<6F>rateur <20> ou <3B>, il suffit
|
|||
|
qu'une seule des conditions qu'il rassemble soit vraie : </p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li> si <em>toutes</em> les conditions sont rassembl<62>es, la condition
|
|||
|
d'ensemble l'est aussi ;</li>
|
|||
|
|
|||
|
<li> si <em>une partie seulement</em> de ces conditions est rassembl<62>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<4F>rateurs arithm<68>tiques</h3>
|
|||
|
|
|||
|
<p>
|
|||
|
Le shell permet d'op<6F>rer des calculs arithm<68>tiques, m<>me s'il est moins
|
|||
|
puissant que d'autres langages (Perl, Scheme, C, etc.) pour cela.
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
Les op<6F>rateurs sont les suivants :
|
|||
|
</p>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li> <code>-eq</code> (<i>equal</i>) : <20> <3B>gal <20> <3B> (signe
|
|||
|
<EFBFBD> = <3B>) ;</li>
|
|||
|
|
|||
|
<li> <code>-ne</code> (<i>not equal</i>) : <20> diff<66>rent
|
|||
|
de <3B> (signe <20> ≠ <3B>) ;</li>
|
|||
|
|
|||
|
<li> <code>-gt</code> (<i>greater than</i>) : <20> strictement
|
|||
|
sup<EFBFBD>rieur <20> <3B> (signe <20> > <3B>) ;</li>
|
|||
|
|
|||
|
<li> <code>-lt</code> (<i>lesser than</i>) : <20> strictement
|
|||
|
inf<EFBFBD>rieur <20> <3B> (signe <20> < <3B>) ;</li>
|
|||
|
|
|||
|
<li> <code>-ge</code> (<i>greater or equal</i>) : <20> sup<75>rieur
|
|||
|
ou <20>gal <20> <3B> (signe <20> ≥ <3B>) ;</li>
|
|||
|
|
|||
|
<li> <code>-le</code> (<i>lesser or equal</i>) : <20> inf<6E>rieur
|
|||
|
ou <20>gal <20> <3B> (signe <20> ≤ <3B>) ;</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p>
|
|||
|
On utilise ces op<6F>rateurs entre deux nombres ou variables
|
|||
|
num<EFBFBD>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<65>cutez ce programme, vous obtenez :
|
|||
|
</p>
|
|||
|
|
|||
|
<pre>
|
|||
|
C'est normal.
|
|||
|
C'est normal.
|
|||
|
</pre>
|
|||
|
|
|||
|
|
|||
|
<h3>Op<4F>rateurs sur les fichiers</h3>
|
|||
|
|
|||
|
<p>
|
|||
|
Une grande partie de la puissance du shell se d<>ploie dans sa facult<6C> de
|
|||
|
manipuler des fichiers.
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
Les principaux op<6F>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<EFBFBD>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
|
|||
|
<EFBFBD>tre lu ;</li>
|
|||
|
|
|||
|
<li> <code>-w</code> (<i>writable</i>) : v<>rifie si un fichier peut
|
|||
|
<EFBFBD>tre <20>crit ou modifi<66> ;</li>
|
|||
|
|
|||
|
<li> <code>-x</code> (<i>writable</i>) : v<>rifie si un fichier peut
|
|||
|
<EFBFBD>tre ex<65>cut<75> ;</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<EFBFBD>: Baptiste M<>l<EFBFBD>s.
|
|||
|
Derni<EFBFBD>re modification le <date value="$Date: 2005-09-07 10:03:55 $" />.
|
|||
|
</div>
|
|||
|
|
|||
|
</body>
|
|||
|
</html>
|