IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

[bash] opérateurs conditionnels et regroupement de commandes.


Sujet :

Shell et commandes GNU

  1. #1
    Membre confirmé Avatar de ben.IT
    Homme Profil pro
    Inscrit en
    Janvier 2009
    Messages
    431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Janvier 2009
    Messages : 431
    Points : 486
    Points
    486
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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.
    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.

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    commands between parentheses causes a subshell environment to be created
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Membre confirmé Avatar de ben.IT
    Homme Profil pro
    Inscrit en
    Janvier 2009
    Messages
    431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Janvier 2009
    Messages : 431
    Points : 486
    Points
    486
    Par défaut
    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 ?
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  4. #4
    Membre confirmé Avatar de ben.IT
    Homme Profil pro
    Inscrit en
    Janvier 2009
    Messages
    431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Janvier 2009
    Messages : 431
    Points : 486
    Points
    486
    Par défaut
    merci pour ta réponse,
    NB: on n'utilise pas return pour afficher le résultat d'une fonction.
    pourrais tu préciser ce que tu entends ?
    merci.
    ben

  5. #5
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    man bash
    $ 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.
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    echo "$$ - $BASHPID"; (echo "$$ - $BASHPID")
    4092 - 4092
    4092 - 4154
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  6. #6
    Membre confirmé Avatar de ben.IT
    Homme Profil pro
    Inscrit en
    Janvier 2009
    Messages
    431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Janvier 2009
    Messages : 431
    Points : 486
    Points
    486
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  7. #7
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    quant à return je pensais à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  8. #8
    Membre confirmé Avatar de ben.IT
    Homme Profil pro
    Inscrit en
    Janvier 2009
    Messages
    431
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Janvier 2009
    Messages : 431
    Points : 486
    Points
    486
    Par défaut
    ok, no problemo
    merci à toi, N_BaH
    à bientôt,
    benoît

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Regroupement de commandes
    Par Alikendarfen dans le forum Algorithmes et structures de données
    Réponses: 30
    Dernier message: 08/08/2011, 11h07
  2. [AC-2003] regrouper les commandes de navigation (fonctions?)
    Par minot83 dans le forum IHM
    Réponses: 4
    Dernier message: 13/02/2011, 10h58
  3. Fonction qui regroupe les commandes sql
    Par champomy62 dans le forum VB.NET
    Réponses: 13
    Dernier message: 28/10/2010, 01h27
  4. [gcc] opérateur conditionnel ternaire "?:"
    Par mamelouk dans le forum C++
    Réponses: 33
    Dernier message: 22/08/2007, 14h46
  5. Réponses: 3
    Dernier message: 20/09/2005, 18h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo