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 05/04/2011, 12h53   #1
Candidat au titre de Membre du Club
 
Homme
Inscription : mars 2007
Messages : 22
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 27
Localisation : Belgique

Informations forums :
Inscription : mars 2007
Messages : 22
Points : 12
Points : 12
Envoyer un message via ICQ à Yokav Envoyer un message via AIM à Yokav Envoyer un message via MSN à Yokav Envoyer un message via Yahoo à Yokav Envoyer un message via Skype™ à Yokav
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 :
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
Yokav est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 05/04/2011, 16h58   #2
Membre Expert
 
Homme Alexis
Intégrateur d'Exploitation
Inscription : février 2003
Messages : 876
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 32
Localisation : France

Informations professionnelles :
Activité : Intégrateur d'Exploitation
Secteur : Biens de consommation

Informations forums :
Inscription : février 2003
Messages : 876
Points : 1 619
Points : 1 619
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
Déjà, les tableaux associatifs sont possibles en bash :
Code :
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 :
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...
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 40
Vieux 05/04/2011, 17h22   #3
Candidat au titre de Membre du Club
 
Homme
Inscription : mars 2007
Messages : 22
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 27
Localisation : Belgique

Informations forums :
Inscription : mars 2007
Messages : 22
Points : 12
Points : 12
Envoyer un message via ICQ à Yokav Envoyer un message via AIM à Yokav Envoyer un message via MSN à Yokav Envoyer un message via Yahoo à Yokav Envoyer un message via Skype™ à Yokav
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.
Yokav est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 06/04/2011, 10h06   #4
Candidat au titre de Membre du Club
 
Homme
Inscription : mars 2007
Messages : 22
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 27
Localisation : Belgique

Informations forums :
Inscription : mars 2007
Messages : 22
Points : 12
Points : 12
Envoyer un message via ICQ à Yokav Envoyer un message via AIM à Yokav Envoyer un message via MSN à Yokav Envoyer un message via Yahoo à Yokav Envoyer un message via Skype™ à Yokav
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 :
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
Yokav est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 06/04/2011, 14h21   #5
Membre Expert
 
Homme Alexis
Intégrateur d'Exploitation
Inscription : février 2003
Messages : 876
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 32
Localisation : France

Informations professionnelles :
Activité : Intégrateur d'Exploitation
Secteur : Biens de consommation

Informations forums :
Inscription : février 2003
Messages : 876
Points : 1 619
Points : 1 619
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
${!... 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
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 06/04/2011, 15h31   #6
Candidat au titre de Membre du Club
 
Homme
Inscription : mars 2007
Messages : 22
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 27
Localisation : Belgique

Informations forums :
Inscription : mars 2007
Messages : 22
Points : 12
Points : 12
Envoyer un message via ICQ à Yokav Envoyer un message via AIM à Yokav Envoyer un message via MSN à Yokav Envoyer un message via Yahoo à Yokav Envoyer un message via Skype™ à Yokav
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 :
1
2
3
4
5
 
    x="$1_menu[@]"
    y="!$1_menu[*]"
    declare -a desc=( "${!x}" )
    declare -a fonc=( "${!y}" )
Yokav est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/04/2011, 09h28   #7
Membre Expert
 
Homme Alexis
Intégrateur d'Exploitation
Inscription : février 2003
Messages : 876
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 32
Localisation : France

Informations professionnelles :
Activité : Intégrateur d'Exploitation
Secteur : Biens de consommation

Informations forums :
Inscription : février 2003
Messages : 876
Points : 1 619
Points : 1 619
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
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 :
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 :/
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/04/2011, 14h01   #8
Candidat au titre de Membre du Club
 
Homme
Inscription : mars 2007
Messages : 22
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 27
Localisation : Belgique

Informations forums :
Inscription : mars 2007
Messages : 22
Points : 12
Points : 12
Envoyer un message via ICQ à Yokav Envoyer un message via AIM à Yokav Envoyer un message via MSN à Yokav Envoyer un message via Yahoo à Yokav Envoyer un message via Skype™ à Yokav
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é.
Yokav est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 01h48.


 
 
 
 
Partenaires

Hébergement Web