Précédent   Forum des professionnels en informatique > Systèmes > Linux > Applications > Shell
Shell Vos questions sur l'utilisation des commandes shell
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 17/03/2011, 21h52   #1
Membre éprouvé
 
Avatar de ben.IT
 
Homme Benoît
Inscription : janvier 2009
Messages : 392
Détails du profil
Informations personnelles :
Nom : Homme Benoît
Âge : 24
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : janvier 2009
Messages : 392
Points : 438
Points : 438
Par défaut [bash] opérateurs conditionnels et regroupement de commandes.

Salut à tous,
dans mes scripts shell, j'utilise souvent une fonction qui rend un code de retour.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
 1 #!/bin/bash -x
  2 
  3 function_test ()
  4 {
  5         case $1 in
  6         [0-9])
  7                 echo "\$1 valide"
  8                 ;;
  9         *)
 10                 echo "erreur \$1"
 11                 exit 2
 12                 ;;
 13         esac
 14         return $1
 15 }
Selon la valeur de ce code de retour, j'effectue un traitement différent; pour cela, j'effectue le code :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
 16 
 17 #code classique, long ! 
 18 #analyse du code de retour de la fonction et traitement adequat
 19 function_test $1
 20 if [ $? -eq 0 ]
 21 then
 22         echo "traitement ok"
 23         date
 24         echo "ok"
 25 else
 26         echo "traitement erreur"
 27         uptime
 28         exit 1
 29 fi
Je souhaiterai "compacter" ce code afin de réduire la taille de mes scripts.
Pour cela, j'utilise les opérateurs d’exécution conditionnelle && et || et j'utilise un opérateur de groupement { }.

Code :
1
2
3
4
 
 31 #syntaxe 1
 32 #utilisation de l execution conditionnelle. groupement des instructions avec {}. fonctionne OK.
 33 [ $? -eq 0 ] && { echo "traitement ok" ;date ; echo "ok"; } ||  { echo "traitement erreur." ; uptime ; exit 1 ; }
Ce code fonctionne, le exit est bien pris en compte et les instructions suivantes ne sont pas traitées en cas d'erreur.

J'ai également voulu tester les () pour grouper mes commandes, mais le résultat est différent, la suite des commande est exécutée, malgré le exit.
Code :
1
2
3
4
 
 35 #syntaxe 2 
 36 #utilisation de l execution conditionnelle. groupement des instructions avec ( ) 
 37 [ $? -eq 0 ] && ( echo "traitement ok" ;date ; echo "ok"; ) ||  ( echo "traitement erreur." ; uptime ; exit 1 ; )

Voici le résultat avec la syntaxe 1 :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
[benoit@benoit src]$ if.sh 1
+ function_test 1
+ case $1 in
+ echo '$1 valide'
$1 valide
+ return 1
+ '[' 1 -eq 0 ']'
+ echo 'traitement erreur.'
traitement erreur.
+ uptime
 21:50:40 up  2:42,  3 users,  load average: 0.00, 0.01, 0.05
+ exit 1
Voici le résultat avec la syntaxe 2, exécution se poursuit :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[benoit@benoit src]$ if.sh 1
+ function_test 1
+ case $1 in
+ echo '$1 valide'
$1 valide
+ return 1
+ '[' 1 -eq 0 ']'
+ echo 'traitement erreur.'
traitement erreur.
+ uptime
 21:52:00 up  2:43,  4 users,  load average: 0.04, 0.03, 0.05
+ exit 1
+ echo 'la suite des instructions'
la suite des instructions
J'ai effectué une recherche sur les opérateurs de groupement de commandes, voici ce que j'ai trouvé et qui ne m'explique pas la différence de comportement entre les 2 codes.
Citation:
3.2.4.3 Grouping Commands

Bash provides two ways to group a list of commands to be executed as a unit. When commands are grouped, redirections may be applied to the entire command list. For example, the output of all the commands in the list may be redirected to a single stream.

()

( list )

Placing a list of commands between parentheses causes a subshell environment to be created (see Command Execution Environment), and each of the commands in list to be executed in that subshell. Since the list is executed in a subshell, variable assignments do not remain in effect after the subshell completes.
{}

{ list; }

Placing a list of commands between curly braces causes the list to be executed in the current shell context. No subshell is created. The semicolon (or newline) following list is required.

In addition to the creation of a subshell, there is a subtle difference between these two constructs due to historical reasons. The braces are reserved words, so they must be separated from the list by blanks or other shell metacharacters. The parentheses are operators, and are recognized as separate tokens by the shell even if they are not separated from the list by whitespace.

The exit status of both of these constructs is the exit status of list.

Comment expliquer cette différence de comportement ?
merci d'avance,
ben.
__________________
Meet the free software gang
ben.IT est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 17/03/2011, 22h40   #2
Expert Confirmé Sénior
 
Avatar de N_BaH
 
Inscription : février 2008
Messages : 2 070
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 2 070
Points : 4 153
Points : 4 153
Citation:
commands between parentheses causes a subshell environment to be created
Citation:
commands between curly braces causes the list to be executed in the current shell context.
No subshell is created.
c'est plus clair comme ça ?

mettre exit dans un subshell fait quitter le subshell, pas le shell courant.
Code :
1
2
3
4
(exit 1); echo $?
1
(exit 2; echo bla); echo $?
2
NB: on n'utilise pas return pour afficher le résultat d'une fonction.
N_BaH est déconnecté   Envoyer un message privé Réponse avec citation 30
Vieux 17/03/2011, 22h48   #3
Membre éprouvé
 
Avatar de ben.IT
 
Homme Benoît
Inscription : janvier 2009
Messages : 392
Détails du profil
Informations personnelles :
Nom : Homme Benoît
Âge : 24
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : janvier 2009
Messages : 392
Points : 438
Points : 438
c'est ce que je me disais mais pourquoi lorsque j'affiche $$, dans les parenthèses ou les accolades, je ne vois pas un shell id different ?
Citation:
Placing a list of commands between parentheses causes a subshell environment to be created (see Command Execution Environment), and each of the commands in list to be executed in that subshell.
Code :
1
2
3
4
5
6
7
8
9
10
11
12
 
17 function_test $1
 18 #syntaxe 1
 19 #utilisation de l execution conditionnelle. groupement des instructions avec {}. fonctionne OK.
 20 [ $? -eq 0 ] && { echo "traitement ok : $$" ;date ; echo "ok"; } ||  { echo "traitement erreur." ; uptime ; exit 1 ; }
 21 
 22 #syntaxe 2 
 23 #utilisation de l execution conditionnelle. groupement des instructions avec ( ); en cas d erreur le exit ne termine pas le script. 
 24 [ $? -eq 0 ] && ( echo "traitement ok : $$" ;date ; echo "ok"; ) ||  ( echo "traitement erreur." ; uptime ; exit 1 ; )
 25 
 26 
 27 echo "la suite des instructions"
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
benoit@benoit src]$ if.sh 0
+ function_test 0
+ case $1 in
+ echo '$1 valide'
$1 valide
+ return 0
+ '[' 0 -eq 0 ']'
+ echo 'traitement ok : 3517'
traitement ok : 3517
+ date
Thu Mar 17 22:48:03 CET 2011
+ echo ok
ok
+ '[' 0 -eq 0 ']'
+ echo 'traitement ok : 3517'
traitement ok : 3517
+ date
Thu Mar 17 22:48:03 CET 2011
+ echo ok
ok
+ echo 'la suite des instructions'
la suite des instructions
__________________
Meet the free software gang
ben.IT est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 17/03/2011, 22h57   #4
Membre éprouvé
 
Avatar de ben.IT
 
Homme Benoît
Inscription : janvier 2009
Messages : 392
Détails du profil
Informations personnelles :
Nom : Homme Benoît
Âge : 24
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : janvier 2009
Messages : 392
Points : 438
Points : 438
merci pour ta réponse,
Citation:
NB: on n'utilise pas return pour afficher le résultat d'une fonction.
pourrais tu préciser ce que tu entends ?
merci.
ben
__________________
Meet the free software gang
ben.IT est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 17/03/2011, 22h57   #5
Expert Confirmé Sénior
 
Avatar de N_BaH
 
Inscription : février 2008
Messages : 2 070
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 2 070
Points : 4 153
Points : 4 153
man bash
Citation:
$ Se transforme en PID de l'interpréteur. Dans un sous-interpréteur (), il se transforme en PID de l'interpréteur et non pas du sous-interpréteur.
Citation:
BASHPID Se transforme en PID de l'interpréteur bash courant. Diffère de $$ sous certaines conditions, comme dans les sous-interpréteurs ne nécessitant pas que bash soit réinitialisé.
Code :
1
2
3
echo "$$ - $BASHPID"; (echo "$$ - $BASHPID")
4092 - 4092
4092 - 4154
N_BaH est déconnecté   Envoyer un message privé Réponse avec citation 30
Vieux 17/03/2011, 23h05   #6
Membre éprouvé
 
Avatar de ben.IT
 
Homme Benoît
Inscription : janvier 2009
Messages : 392
Détails du profil
Informations personnelles :
Nom : Homme Benoît
Âge : 24
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : janvier 2009
Messages : 392
Points : 438
Points : 438
Merci N_BaH, je l'ignorais, je n'avais jamais utilisé cette variable BASHPID.
effectivement le BASHPID est identique avec les { } et est différent avec les ( ) :
Code :
1
2
3
4
5
6
7
8
 
 18 #syntaxe 1
 19 #utilisation de l execution conditionnelle. groupement des instructions avec {}. fonctionne OK.
 20 [ $? -eq 0 ] && { echo "traitement ok {} : $BASHPID" ;date ; echo "ok"; } ||  { echo "traitement erreur." ; uptime ; exit 1 ; }
 21 
 22 #syntaxe 2 
 23 #utilisation de l execution conditionnelle. groupement des instructions avec ( ); en cas d erreur le exit ne termine pas le script. 
 24 [ $? -eq 0 ] && ( echo "traitement ok () : $BASHPID" ;date ; echo "ok"; ) ||  ( echo "traitement erreur." ; uptime ; exit 1 ; )
Code :
1
2
3
4
5
6
7
8
9
10
 
[benoit@benoit src]$ if.sh 0
$1 valide
traitement ok {} : 3727
Thu Mar 17 23:04:31 CET 2011
ok
traitement ok () : 3729
Thu Mar 17 23:04:31 CET 2011
ok
la suite des instructions
Qu'entends tu par "on n'utilise pas return pour afficher le résultat d'une fonction." ?
je suis preneur de tout bon conseil
merci pour tes réponses ,
ben
__________________
Meet the free software gang
ben.IT est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 17/03/2011, 23h13   #7
Expert Confirmé Sénior
 
Avatar de N_BaH
 
Inscription : février 2008
Messages : 2 070
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 2 070
Points : 4 153
Points : 4 153
quant à return je pensais à ça :
Code :
1
2
3
4
5
6
7
8
9
maFunc () { return $1;}
maFunc bla
bash: return: bla : argument numérique nécessaire
maFunc 255; echo $?
255
maFunc 256; echo $?
0
maFunc 257; echo $?
1
lol
N_BaH est déconnecté   Envoyer un message privé Réponse avec citation 30
Vieux 17/03/2011, 23h15   #8
Membre éprouvé
 
Avatar de ben.IT
 
Homme Benoît
Inscription : janvier 2009
Messages : 392
Détails du profil
Informations personnelles :
Nom : Homme Benoît
Âge : 24
Localisation : France, Puy de Dôme (Auvergne)

Informations forums :
Inscription : janvier 2009
Messages : 392
Points : 438
Points : 438
ok, no problemo
merci à toi, N_BaH
à bientôt,
benoît
__________________
Meet the free software gang
ben.IT est déconnecté   Envoyer un message privé Réponse avec citation 10
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 19h37.


 
 
 
 
Partenaires

Hébergement Web