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 :

[SCRIPT] Utilisation de plusieurs commandes CASE imbriquées


Sujet :

Shell et commandes GNU

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2014
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2014
    Messages : 17
    Points : 8
    Points
    8
    Par défaut [SCRIPT] Utilisation de plusieurs commandes CASE imbriquées
    Bonjour à toutes et à tous,

    Je suis en train de réaliser un script shell et je rencontre un problème avec l'utilisation de la commande case.

    J'ai eu beau chercher sur le net, je n'ai rien trouvé de concluant, c'est pourquoi je me tourne vers vous.

    Un exemple valant mieux qu'une explication approximative, regardez ci-dessous ce que j'aimerais faire :

    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    while :
    do
    echo "Choix : $CHOIX"
    echo "Nom :"
    read NOM
     
    echo "Bla bla bla"
     
    echo "Choix :"
    read CHOIX
     
    case $CHOIX in 
     
    1 | 2 )
     
    mes commandes ....
     
    if [[ $CHOIX == "1" ]]
    then
    echo "Rep :"
    read REP
     
    case $REP in
    "o" ) echo "bidule"
    CHOIX=11
    ;;
    "n" ) echo "chouette"
    CHOIX=5
    ;;
    * ) echo "erreur"
    ;;
    esac
     
    else
     
    echo "bye"
    break
    fi
    ;;
     
    3 | 11 )
     
    mes commandes ....
     
    if [[ $CHOIX == "11" ]]
    then
    echo "Rep :"
    read REP
     
    case $REP in
    "o" ) echo "bidule"
    CHOIX=12
    ;;
    "n" ) echo "chouette"
    CHOIX=5
    ;;
    * ) echo "erreur"
    ;;
    esac
     
    else
     
    echo "bye"
    break
    fi
    ;;
     
    4 | 12 )
     
    mes commandes ....
     
    if [[ $CHOIX == "12" ]]
    then
    echo "bye bye"
    break
     
    else
     
    echo "bye"
    break
    fi
    ;;
     
    5 )
     
    echo "Bye"
    break
    ;;
     
    * )
     
    echo "erreur"
    ;;
     
    esac
    done
    Je rencontre donc un problème dans cette partie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    case $REP in
    "o" ) echo "bidule"
    CHOIX=11
    ;;
    "n" ) echo "chouette"
    CHOIX=5
    ;;
    * ) echo "erreur"
    ;;
    esac
    Je rentre bien dans ma boucle if, ainsi que dans mon case donc il prend bien l'entrée clavier et affiche bien le "echo" suivant ce que je saisis au clavier.
    Mon problème se situe précisément au moment où j’attribue une valeur à ma variable CHOIX, pensant que le script va continuer et passer à "l'étape 11".
    Mais ce n'est visiblement pas possible où je m'y prend très mal.

    En fait, ce que fait mon script, c'est qu'il m'affiche le "echo" puis revient directement au début de la boucle while et donc de mon script en me demandant de saisir le "Nom".
    Et surtout, il ne m'affiche pas d'erreur donc la syntaxe ne doit pas être mauvaise.

    J'ai mis un echo "Choix : $CHOIX" au début afin de voir ce qui se passait au moment du passage de la valeur dans la variable, et lorsque c'est une valeur prévue, par exemple 11 ou 5 comme indiqué ci-dessus, la variable CHOIX la prend bien en compte par contre lorsque c'est une autre valeur, la variable CHOIX garde la dernière valeur correct attendue, dans mon cas c'était 1 alors que j'avais saisi 42 au clavier pour REP.

    J'espère que j'ai été assez claire dans mes explications mais si ce n'est pas le cas, n'hésitez pas à me poser vos questions sur les parties qui restent floues.

    Mais je pense, en gros, que vous voyez ce que je veux faire donc si vous pouvez me donner un coup de main (pas un coup de pied ^^) pour résoudre ce problème ou me conseiller, je suis preneur.

    Si vous connaissez une autre méthode pour réaliser ce que je veux faire, n'hésitez pas, je prend aussi.
    En vous remerciant par avance pour vos réponses.

    Bien cordialement,

    Julien.

  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 391
    Points
    19 391
    Par défaut
    Bonjour,

    si je résume, tu veux, tant que $CHOIX a une valeur, exécuter CASE $CHOIX, c'est ça ?

    <hs>
    les conditions simples ne requièrent qu'un simple test.
    par convention, les variables ne devraient pas être entièrement en majuscules (les scripts systèmes en ont, mais ce n'est pas la seule erreur qui y est faite).
    </hs>
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 280
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 280
    Points : 12 729
    Points
    12 729
    Par défaut
    Bonjour,

    Ton problème est sur le fait que le "case" pour la partie "CHOIX" est déjà calculé, tu ne peux pas la changer en cours de route.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    CHOIX=5
    case $CHOIX in
    5 ) CHOIX=6
    ;;
    6 ) CHOIX=7 #ici pour le case, la valeur qui est à vérifier est 5 (et de toute façon, il ne passe pas par là puisque le 1er cas du case est juste)
    ;;
    esac
    Cordialement.

  4. #4
    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 391
    Points
    19 391
    Par défaut
    en bash, il est possible de poursuivre (pas reprendre) le déroulement d'un case, avec ;& à la place de ;; :
    Code BASH : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ var=3
    $ case $var in
    >    3) var=5 ;&
    >    5) echo $var ;;
    > esac
    5
    il faut absolument que le cas soit après la redéfinition de la variable.
    ça ne me semble pas hyper fiable :/
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  5. #5
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 280
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 280
    Points : 12 729
    Points
    12 729
    Par défaut
    Fonctionne pas terrible à priori:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $ CHOIX=3
    $ case $CHOIX in
    > 3 ) CHOIX=4 ;&
    > 5 ) echo $CHOIX
    > ;;
    > esac
    4
    Cordialement.

  6. #6
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 458
    Points
    13 458
    Par défaut
    Bonjour

    Euh... Ce code fait ce qu'on attend de lui. Non?
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  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 391
    Points
    19 391
    Par défaut
    je n'ai alors pas compris comment ça fonctionne.
    Citation Envoyé par man bash
    Si ;& est utilisé au lieu de ;;, l'exécution continue avec la liste associée au jeu de motifs suivant.
    Si ;;& est utilisé au lieu de ;;, l'interpréteur essaye la liste de motifs suivante, si elle existe, et exécute toute liste associée à un motif correspondant.
    donc, ça ne peut pas s'appliquer ici.
    dans les deux cas, le motif n'est pas rééxaminé, si il est réaffecté.

    EDIT:
    Citation Envoyé par Flodelarab
    Ce code fait ce qu'on attend de lui. Non?
    ça dépend de ce qu'on attend de lui !
    si j'attends qu'il fasse le café, je peux attendre longtemps
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2014
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2014
    Messages : 17
    Points : 8
    Points
    8
    Par défaut
    Bonjour,

    Merci d'avoir déplacé ma demande au bon endroit et merci également pour toutes vos réponses.

    En fait, ce que je souhaite faire c'est :

    L'utilisateur exécute le script qui lui demande dans un premier temps un nom.
    Donc l'utilisateur renseigne ce nom et le script lui affiche plusieurs choix possibles suivant ce qu'il veut faire.
    Pour information, prendre en compte que script affiche des informations, supprime ces informations, et vérifie que ces informations sont bien supprimées.

    Donc dans les choix possible on :
    Choix 1 ou 2 : exécute tout le script étape par étape ou affiche seulement les informations
    Choix 3 ou 11 : supprime les informations
    Choix 4 ou 12 : vérifie la bonne suppression ds informations
    Choix 5 : quitter l'exécution du script
    Choix * : erreur, veuillez saisir une valeur attendue

    Pour les choix 2, 3 et 4, je n'ai pas trop de problème.

    C'est lorsque le choix 1 est sélectionné que ça m'embête, car il est exécuté étape par étape.
    En faite, pour résumer, lorsque l'utilisateur choisit le choix numéro 1, je voudrais qu'il se passe la chose suivante :

    Affichage des informations
    Puis l'utilisateur choisi s'il veut continuer ou quitter.

    S'il veut continuer, il passe à la suppression correspondant au choix numéro 11.
    Pourquoi 11 et pas 3 parce que j'ai un if qui me détecte si choix==11 et si c'est le cas il me propose de continuer ou de m'arrêter alors que le choix==3 quitte tout simplement et ne passe pas dans le if.

    S'il veut quitter, il passe au choix numéro 5 (mais là je peux faire autrement, un echo "au revoir" suivi d'un break et c'est fini)
    C'est le même principe qui est employé pour la suppression et la vérification.

    Avec ces nouvelles explications, que j'espère plus clair pour vous, est-ce qu'il y a possibilité de faire quelques chose en gardant la méthode de départ ?

    Si ce n'est pas possible c'est que ma méthode n'est pas bonne, en connaissez-vous une autre qui me permettrait de faire ce que je veux ?
    Car je voulais faire ainsi pour simplifier et éviter d'avoir plein de ligne de code similaire.
    Car sinon je laisse mes choix 2, 3, 4, 5 et * ainsi et dans mon 1 au lieu de faire appel à CASE, je regroupe à l’intérieur mes choix 2, 3 et 4, c'est moche mais je suis sûr que ça fonctionne au moins.

    Ou alors peut-être, faire une fonction pour afficher les info, une autre pour les supprimer, une autre pour vérifier la bonne suppression, une autre pour quitter et une dernière pour une erreur de saisie.
    Et je ferais ensuite appel à ces fonctions dans chaque choix possible du CASE, avec une particularité pour le choix 1 ou je ferais des if qui prendraient en compte l'avis de l'utilisateur avant d’exécuter une nouvelle fonction.

    Pensez-vous que ce soit viable comme méthode ?

    <hs> je ne savais pas qu'il ne fallait pas déclarer les variables uniquement en majuscule, je l'ai fait pas souci de visibilité, merci pour l'info </hs>

    Merci encore une fois pour le temps que vous accordez à mon problème.

    Bonne journée.

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 984
    Points
    30 984
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Julien33400 Voir le message
    Ou alors peut-être, faire une fonction pour afficher les info, une autre pour les supprimer, une autre pour vérifier la bonne suppression, une autre pour quitter et une dernière pour une erreur de saisie.
    Et je ferais ensuite appel à ces fonctions dans chaque choix possible du CASE, avec une particularité pour le choix 1 ou je ferais des if qui prendraient en compte l'avis de l'utilisateur avant d’exécuter une nouvelle fonction.

    Pensez-vous que ce soit viable comme méthode ?
    Bonjour

    C'est la méthode préconisée dans tout cours d'algo (et qui vient d'ailleurs toute seule à l'esprit quand on réfléchit aux possibilités). On décompose les actions en actions élémentaires dévolues à des fonctions dédiées puis on appelle telle ou telle séquence de fonctions selon les choix demandés. Excepté pour l'erreur de saisie qui est fortement liée au choix de l'utilisateur et qui n'a alors pas besoin de fonction spéciale...

    Citation Envoyé par Julien33400 Voir le message
    Je rentre bien dans ma boucle if,
    Ouais super. Va ouvrir tes livres de cours pour relire ce qu'est une boucle...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 458
    Points
    13 458
    Par défaut
    éviter d'avoir plein de ligne de code similaire.
    Pour éviter d'avoir du code similaire, on utilise des fonctions.

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function toto {
        echo 4
        return 3
    }
    $ toto
    4
    $ echo $?
    3
    $ var=$(toto)
    $ echo $?
    3
    $ echo $var
    4
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  11. #11
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 280
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 280
    Points : 12 729
    Points
    12 729
    Par défaut
    -Factorise ton code à l'aide de fonctions comme on te le suggère.
    -Et soit tu revois ta structure de "case" en l'intégrant dans une boucle while (mais quant on a des imbrications de case, cela devient vite compliqué ), soit tu remplaces tous ces "case" par des "if-then-elif-else".
    Cordialement.

  12. #12
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2014
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2014
    Messages : 17
    Points : 8
    Points
    8
    Par défaut
    Merci pour toutes vos réponses, elles m'ont été très utiles.

    J'ai donc suivi vos conseils, utilisation de fonctions et remplacement de case par des if.
    Cela fonctionne très bien.

    Cependant, j'ai un petit soucis.

    Dans mon script, des commandes sont exécutées et cela prend entre 10 et 30 secondes, rien de grave, l’utilisateur est averti par un message.

    Mais, car il y a toujours un mais, si jamais l'utilisateur est impatient et tape sur entrée pendant l’exécution des ces commandes, ça la garde en mémoire et lors du prochain read, dans mon cas celui concernant le CHOIX, j'ai une erreur.

    Donc j'aimerais savoir s'il y avait une astuce pour éviter de lire au clavier pendant l'exécution de ces commandes ou tout autre méthode qui pourrait m'éviter ce problème.

    Merci pour toute l'aide que vous m'apportez.

  13. #13
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 458
    Points
    13 458
    Par défaut
    La question, c'est plutôt "pourquoi un appui innocent sur la touche entrée provoque-t-elle une erreur ?"

    Sinon, tu peux rediriger l'entrée standard dans la poubelle /dev/null avant de lancer les commandes et récupérer l'entrée standard après les commandes.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  14. #14
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2014
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2014
    Messages : 17
    Points : 8
    Points
    8
    Par défaut
    Bonjour,

    Merci pour votre réponse.

    L'erreur n'en est pas vraiment une, c'est juste que vu que la dernière touche tapée est gardée en mémoire, lorsque que le script arrive au read CHOIX, il la prend en compte et si ce n'est pas quelque chose qui est attendu ça me génère une erreur vu que seul 1,2,3,4 et 5 sont attendus, donc l'utilisateur doit à nouveau faire un choix.

    Pour l'envoyer vers la poubelle c'est ça je pense :
    stdin < /dev/null

    Par contre, je ne vois pas comment récupérer l'entrée standard.

    Peut_être ainsi :
    stdin < 0

    Je ne suis vraiment pas sûr, je préfère demander car si je me retrouve sans clavier ça ne va vraiment pas être pratique pour travailler.

  15. #15
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2014
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2014
    Messages : 17
    Points : 8
    Points
    8
    Par défaut
    Coucou,

    Petit UP s'il vous plait.

    Quelqu'un peut-il m'aider en ce qui concerne la question précédente ?

    Par avance merci.

    Bonne journée.

  16. #16
    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 391
    Points
    19 391
    Par défaut

    keskidi ?

    si tu détruire une variable, tu l'unset.
    si tu veux que sa valeur soit nulle, tu lui assignes une valeur nulle !
    c'est tout.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  17. #17
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 280
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 280
    Points : 12 729
    Points
    12 729
    Par défaut
    Son problème est qu'il veut vider stdin avant de faire son read...

    Il n'y a pas de solution magique pour ça, c'est à toi de faire la boucle pour le vider.

    En bash pas trop ancien, tu as la solution suivante à faire avant ton propre read:
    Ceci force la lecture de 100000 caractères avec un timeout de 0.01 seconde.
    Cordialement.

Discussions similaires

  1. Utilisation de plusieurs boîtes imbriquées
    Par stefsas dans le forum Mise en page CSS
    Réponses: 1
    Dernier message: 19/05/2010, 18h21
  2. Utilisation plusieurs boucles For imbriquées
    Par stick25 dans le forum Général VBA
    Réponses: 2
    Dernier message: 07/04/2010, 18h00
  3. utiliser une seule commande pour créer plusieur fichier
    Par waldomania dans le forum Administration système
    Réponses: 1
    Dernier message: 13/12/2009, 16h43
  4. script qui lance plusieurs commandes dos ?
    Par casier dans le forum Scripts/Batch
    Réponses: 4
    Dernier message: 13/08/2007, 07h47
  5. Utilisation d'un script en ligne de commande
    Par Thylia dans le forum Langage
    Réponses: 5
    Dernier message: 23/01/2006, 16h28

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