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 :

Utiliser des tableaux avec un nom variable


Sujet :

Shell et commandes GNU

  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 24
    Points : 22
    Points
    22
    Par défaut Utiliser des tableaux avec un nom variable
    Bonjour,

    Ce que je cherche ne semble pas être des plus simples et cela fait plusieurs heures que j'essaye de trouver une solution, mais je fais un pas en avant puis un pas en arrière... Alors si vous avez le courage de lire ce qui suit, n'hésitez pas à me donner votre avis !

    Le but est de générer automatiquement des menus en se basant sur des tableaux. Ça aurait été assez simple si il était possible d'utiliser un index de type caractère à la place d'un entier, mais soit. Ayant connaissance de cette limitation, je crée donc deux tableaux avec une correspondance entre les index. Dans le premier tableau je met les descriptions des menus et dans le second tableau je met les fonctions liées à ces descriptions.

    Au finale j'aurais donc IDindex --> Description -> Fonction.

    Le problème que je rencontre c'est lorsque j'essaye de faire passer mes tableaux dans la fonction de génération du menu. J'ai essayé en mettant le tableau en paramètre de la fonction, en faisant un eval directement dans la fonction, etc. Rien de concret n'en ressort.

    Voici un exemple de ce que j'aimerais avoir, je sais que le code n'est pas fonctionnel mais c'est pour que mon charabia soit un peu plus compréhensible...
    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
     
    coucou_desr=("première description du menu" "deuxième desc du menu")
    coucou_fonc=("mapremiere_fonction" "maseconde_fonction")
     
    oleeeee_descr=("première description du menu" "deuxième desc du menu")
    oleeeee_fonc=("mapremiere_fonction" "maseconde_fonction")
     
    function menu_generer() {
        for index in ${!$1_desr[@]}
        do
            echo $index" ) "${$1_desr[$index]}
        done
     
        read "Tapez le numéro de l'index désiré : " choix
     
        if [ -z ${$1_fonc[$choix]} ]
        then
            //execute la fonction ${$1_fonc[$choix]}
        fi
    }
     
    menu_generer coucou
    menu_generer oleeeee

  2. #2
    Membre chevronné

    Homme Profil pro
    Responsable projets techniques
    Inscrit en
    Février 2003
    Messages
    980
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Responsable projets techniques
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Février 2003
    Messages : 980
    Points : 1 894
    Points
    1 894
    Par défaut
    Déjà, les tableaux associatifs sont possibles en bash :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $ cat menu.sh
    #!/bin/bash
     
    declare -A menu_list
    menu_list=(["A"]="menu A" ["B"]="menu B")
     
    for elem in ${!menu_list[*]} ; do
            echo "\"${elem}\" : "${menu_list[${elem}]} ;
    done
    $ bash menu.sh
    "A" : menu A
    "B" : menu B
    Mais pour ton problème, ton idée me semble bonne car ça simplifie la saisie du choix par l'utilisateur :

    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
     
    $ cat menu.sh
    #!/bin/bash
     
    coucou_descr=("première description du menu" "deuxième desc du menu")
    coucou_fonc=("mapremiere_fonction" "maseconde_fonction")
     
    oleeeee_descr=("première description du menu" "deuxième desc du menu")
    oleeeee_fonc=("matroisieme_fonction" "maquatrieme_fonction")
     
    function menu_generer() {
        echo "*** Menu "$1" ***"
        x="$1_descr[@]"
        declare -a menu=( "${!x}" )
        eval ix_menu=\${!$1_descr[*]}
        y="$1_fonc[@]"
        declare -a fonc=( "${!y}" )
     
        for index in $ix_menu
        do
            echo $index" ) "${menu[$index]}" ("${fonc[$index]}")"
        done
     
        echo -n "Tapez le numéro de l'index désiré : "
        read choix
     
     
        if [ -n "${fonc[$choix]}" ]
        then
            ${fonc[$choix]}
        fi
    }
     
    function mapremiere_fonction {
        echo "action 001 : mapremiere_fonction"
    }
     
    function maseconde_fonction {
        echo "action 002 : maseconde_fonction"
    }
     
    function matroisieme_fonction {
        echo "action 003 : matroisieme_fonction"
    }
     
    function maquatrieme_fonction {
        echo "action 004 : maquatrieme_fonction"
    }
     
     
    menu_generer coucou
    echo "***"
    menu_generer oleeeee
    $ bash menu.sh
    *** Menu coucou ***
    0 ) première description du menu (mapremiere_fonction)
    1 ) deuxième desc du menu (maseconde_fonction)
    Tapez le numéro de l'index désiré : 0
    action 001 : mapremiere_fonction
    ***
    *** Menu oleeeee ***
    0 ) première description du menu (matroisieme_fonction)
    1 ) deuxième desc du menu (maquatrieme_fonction)
    Tapez le numéro de l'index désiré : 1
    action 004 : maquatrieme_fonction
    Edit: il y a sans doute plus propre...

  3. #3
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 24
    Points : 22
    Points
    22
    Par défaut
    Salut,

    Un grand merci pour cette réponse rapide et très claire !

    Mon erreur venait de la déclaration d'un tableau avec -a à la place de -A. Et d'après ce que j'avais lu, je pensais qu'il n'était pas possible de créer un tableau associatif avec un index autre qu'un entier. Comme quoi il ne faut pas toujours se fier à ce que l'on peut trouver sur la toile...

    Pour ce qui est du code que tu proposes pour générer le menu, il est fonctionnel c'est parfait. Je n'ai pas encore tout compris je dois avouer , mais grâce à ça j'ai une bonne base à étudier pour réaliser le code que je désire.

    Encore merci.

  4. #4
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 24
    Points : 22
    Points
    22
    Par défaut
    Re,

    Il y a tout de même un bout de ton code que je n'arrive pas à m'expliquer. Il s'agit de la partie ou tu déclares un nouveau tableau contenant l'ancien. "declare -a desc=( "${!x}" )", le point d'exclamation à cet endroit doit signifier qu'on désire récupérer les index hors là on récupère les valeurs...et si on retire ce point d'exclamation cela génère une erreur.

    ${!coucou_menu[@]} = liste des index
    ${coucou_menu[@]} = liste des valeurs


    Si je cherche à comprendre cela, c'est que j'ai une idée pour améliorer la fonction de génération du menu. A la place de partir de deux tableaux différents en respectant une concordance des index, ce qui risque de ne pas toujours arriver. On part d'un seul tableau ayant comme index le nom de la fonction et comme valeur la description de la fonction.
    Ensuite comme dans la fonction de génération du menu que tu as proposées, on crée deux tableaux à partir de l'existant. L'un contenant les index et l'autre contenant les valeurs, ainsi ces deux nouveaux tableaux auront obligatoirement un index d'entier identique.

    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
     
    declare -A coucou_menu
    coucou_menu["fonc1"]="Description de fonc1"
    coucou_menu["fonc2"]="Description de fonc2"
    coucou_menu["fonc3"]="Description de fonc3"
     
    function menu_generer() {
        echo "*** Menu "$1" ***"
        x="$1_menu[@]"
        declare -a desc=( "${x}" )
        declare -a fonc=( "${!x}" )
     
        eval menu_length=\${#$1_menu[@]}
     
        for (( i=0; i<$menu_length; i++ ))
        do
            echo $i" - "${fonc[$i]}" - "${desc[$i]}
        done
    }
     
    menu_generer coucou

  5. #5
    Membre chevronné

    Homme Profil pro
    Responsable projets techniques
    Inscrit en
    Février 2003
    Messages
    980
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Responsable projets techniques
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Février 2003
    Messages : 980
    Points : 1 894
    Points
    1 894
    Par défaut
    ${!... retourne les index pour un tableau associatif (${!ARRAY[*]}); ici, il s'agit d'une référence

    http://tldp.org/LDP/abs/html/bashver2.html#VARREFNEW

  6. #6
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 24
    Points : 22
    Points
    22
    Par défaut
    Intéressant ce système de référence, je ne connaissais pas. Dans ce cas le code devrait ressembler à ceci de ce que j'en déduis, mais ça ne fonctionne pas.
    Le tableau "fonc" reste vide.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        x="$1_menu[@]"
        y="!$1_menu[*]"
        declare -a desc=( "${!x}" )
        declare -a fonc=( "${!y}" )

  7. #7
    Membre chevronné

    Homme Profil pro
    Responsable projets techniques
    Inscrit en
    Février 2003
    Messages
    980
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Responsable projets techniques
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Février 2003
    Messages : 980
    Points : 1 894
    Points
    1 894
    Par défaut
    Effectivement, ça ne semble pas marcher avec les index, je n'ai pas le niveau pour t'expliquer le pourquoi du comment cependant

    Je peux te proposer ce contournement (utilisation de l'ancienne méthode pour les références) :

    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
    $ cat ref.sh
    #!/bin/bash
    
    declare -A coucou_menu
    coucou_menu["fonc1"]="Description de fonc1"
    coucou_menu["fonc2"]="Description de fonc2"
    coucou_menu["fonc3"]="Description de fonc3"
    
    function menu_generer() {
        echo "*** Menu "$1" ***"
        x="$1_menu[@]"
        declare -a desc=( "${!x}" )
        eval declare -a fonc=( "\${!$x}" )
    
        eval menu_length=\${#$1_menu[@]}
    
        for (( i=0; i<$menu_length; i++ ))
        do
            echo $i" - "${fonc[$i]}" - "${desc[$i]}
        done
    }
    
    menu_generer coucou
    $ bash ref.sh
    *** Menu coucou ***
    0 - fonc1 - Description de fonc1
    1 - fonc2 - Description de fonc2
    2 - fonc3 - Description de fonc3
    A noter que l'utilisation d'eval est souvent déconseillée pour des raisons de sécurité, mais pour ce problème, je ne vois pas d'autres solutions :/

  8. #8
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 24
    Points : 22
    Points
    22
    Par défaut
    Merci pour le conseil, je vais me baser là-dessus. En tous cas c'est propre comme code, ça fait plaisir à voir !

    Car au début j'utilisais la fonction eval et voici un exemple de code que j'avais trouvé pour un eval : fonc=($(eval echo $(echo \${!$1_menu[@]}))). Autrement dis, bien moins propre que ce que tu m'as proposé.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 02/03/2015, 09h38
  2. [save] utilisation avec un nom variable
    Par Invité dans le forum MATLAB
    Réponses: 7
    Dernier message: 07/02/2014, 11h31
  3. Réponses: 2
    Dernier message: 22/10/2008, 19h41
  4. Réponses: 22
    Dernier message: 03/01/2008, 22h42
  5. Utiliser des webservices avec nusoap
    Par budiste dans le forum XML/XSL et SOAP
    Réponses: 6
    Dernier message: 30/03/2006, 11h56

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