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 :

Faire un tableau à deux dimensions


Sujet :

Shell et commandes GNU

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 42
    Par défaut Faire un tableau à deux dimensions
    Bonjour à tous,

    J'aimerais réaliser un tableau à deux dimensions. Je veux qu'une valeur du tableau sois affecté par les en-tetes du tableau et le nom de la 1er colonne.

    J'ai vu que pour réaliser un tableau à 2 dimensions: On pouvait utiliser la commande eval.

    J'ai essayer de la mettre en place, mais j'avoue n'avoir pas compris son fonctionnement. Si quelqu'un à un petit script, pour que je comprenne la commande.

    Exemple de ce que j'attend:

    Serveur;Item1;Item2;Item3;Item4;Item5
    Toto;Value1;Value2;Value3;Value4;Value5
    Tata;Value6;Value7;Value8;Value9;Value0

    Merci d'avance à celui qui pourras m'aider

    Cordialement

    Chattam

  2. #2
    Expert confirmé Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 292
    Par défaut
    En ce qui concerne l'écriture d'un tableau, la commande pratique est printf et non eval. Avec printf, tu pourras forcer des formats qui respecteront tes colonnes de tableaux.

    Pour la couleur, il te suffit de te renseigner sur les échappements permettant la couleur en bash (ou ton shell perso).

    Reviens quand tu auras potassé les deux sujets.

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chattam Voir le message
    J'ai vu que pour réaliser un tableau à 2 dimensions: On pouvait utiliser la commande eval.
    Bonjour

    Le shell est un langage très très basique. Le Bourne Shell ne connaissait même pas les tableaux. Ceux-ci sont arrivés avec bash mais ils sont limités à une dimension.

    Alors effectivement, on peut utiliser eval afin de "simuler" deux dimensions. On construit d'abord l'expression voulue en utilisant la première dimension du tableau puis eval l'évalue et renvoie l'élément de la seconde dimension

    Exemple
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ serveur=(item1 item2 item3 item4 item5)
    $ toto=(value1 value2 value3 value4 value5)
    $ tata=(value6 value7 value8 value9 value10)
    $ tab=(serveur toto tata)
    $ eval "echo \${${tab[1]}[3]}"
    value4

    Explication: la valeur "value4" se trouve dans toto[3]. Et la chaine "toto" se trouve dans tab[1]. Donc en partant de tab[1] et en rajoutant [3] et des accolades au bon endroit, on arrivera à la valeur voulue.
    Et donc:
    • echo "${tab[1]}" affiche "toto"
    • echo "${tab[1]}[3]" affiche "toto[3]"
    • echo "\${${tab[1]}[3]}" affiche "${toto[3]}"
    • et pour finir, eval "echo \${${tab[1]}[3]}" évalue l'instruction echo ${toto[3]}. Cette instruction est alors évaluée et exécutée comme si elle avait été tapée dans le script et renvoie donc la valeur de "toto[3]" c'est à dire "value4"


    On peut faire de même pour simuler 3, 4, 5, x dimensions. On rajoute des eval de eval autant qu'il faut (mais ça devient vite illisible)...
    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]

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 660
    Par défaut
    Bonjour,

    bash possède désormais des tableaux associatifs, qui permettent de simuler des tableaux multi-dimensionnels :
    Code BASH : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    declare -A tableau
    tableau=(
       [lin_1,col_1]="blabla_1.1"
       [lin_1,col_2]="blabla_1.2"
       [lin_2,col_1]="blabla_2.1"
    )
    #etc...
    for i in "${!tableau[@]}"
    do
       IFS=',' read l c <<<"$i"
       echo "ligne: $l ; colonne: $c = ${tableau["$l","$c"]}" #autant dire ${tableau[$i]} ;)
    done
    un petit problème peut-être : les tableaux sont hashés, donc il n'est pas facile de les afficher "dans l'ordre"

    tu veux lire un fichier CSV, et constituer le tableau en bash ?

    mais, es-tu certain d'avoir besoin d'un tel tableau ? tu peux nous donner des détails sur tes intentions ?

    PS: y a pas de mal à éviter eval
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 42
    Par défaut
    Je dois récupérer des données sous zabbix et les mettre sous la forme d'un fichier csv(comme l'exemple montrer). Les couleurs était la pour bien faire comprendre ce que je désirais.
    Je dois récupérer des host avec leur items et les valeurs associés.

    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
    #!/bin/bash
     
    url=adresse zabbix
     
     
    function zbx_login {
            resp=$(curl -3 -k -X POST -H 'Content-Type:application/json' -d'{"jsonrpc": "2.0","method":"user.authenticate","params":{"user":"gdi","password":"gd"},"auth": null,"id":0}' $url)
            echo $resp | awk -F=":" -v RS="," '$1~/"result"/ {print}' | cut -d '"' -f4
    }
     
    function zbx_get_host {
            resp=$(curl -3 -k -X POST -H 'Content-Type: application/json' -d "{\"jsonrpc\":\"2.0\",\"method\":\"host.get\",\"params\":{\"output\":\"extend\",\"sortfield\":\"hostid\"},\"auth\":\"$(zbx_login)\",\"id\":0}" $url)
            echo $resp  | awk -F=":" -v RS="," '$1~/"host"/ {print}' | cut -d '"' -f4
    }
     
    function zbx_get_item {
            resp=$(curl -3 -k -X POST -H 'Content-Type: application/json' -d "{\"jsonrpc\":\"2.0\",\"method\":\"item.get\",\"params\":{\"output\":\"extend\",\"host\":\"$1\"},\"auth\":\"$(zbx_login)\",\"id\":0}" $url)
            echo $resp | awk -F=":" -v RS="," '$1~/"itemid"/ {print}' | cut -d '"' -f4
     
    }
     
    function zbx_get_history {
     
            resp=`curl -3 -k -X POST -H 'Content-Type: application/json' -d "{\"jsonrpc\":\"2.0\",\"method\":\"history.get\",\"params\":{\"itemids\":\"$2\",\"history\":[1,2,3,4],\"output\":\"extend\",\"time_from\":\"$3\",\"time_till\":\"$4\",\"limit\":1},\"auth\":\"$(zbx_login)\",\"id\":0}" $url`
            echo $resp | awk -F=":" -v RS="," '$1~/"value"/ {print}' | cut -d '"' -f4
    }
     
     
     
    host=$(zbx_get_host)
    declare -a host_array
     
    host_array=(${host// / })
    rm /home/gd/result.txt 2>/dev/null
    touch /home/gd/result.txt
    declare -a item_array
    for i in ${host_array[@]};
            do
              item=$(zbx_get_item $i)
              item_array=(${item// / })
              echo -n $i";">>/home/gd/result.txt
              for x in ${item_array[@]};
                    do
                      echo -n $x";">>/home/gd/result.txt
                    done
              item_array=()
              echo "" >> /home/gd/result.txt
    done
    Voila mon script, ma fontion login me permet d'avoir accès au serveur zabbix. Ma fonction host me permet de récupérer tt les noms d'hotes. Ma fonction item me donne les items des hotes. la fonction history me donne la valeur des items.
    Ensuite j'ai fait des boucles. Mais le résultat n'est pas exploitable du tout. (j'ai mis une sortie en txt pour visualiser)

    Donc j'essaie de voir comment faire pour le rendu.

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 835
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par chattam Voir le message
    Ma fonction host me permet de récupérer tt les noms d'hotes. Ma fonction item me donne les items des hotes. la fonction history me donne la valeur des items.
    Tu ne voudrais pas nous donner un exemple du résultat renvoyé par les fonctions host, item et history ; puis ensuite nous dire comment tu voudrais agréger ces résultats ensembles ???

    Accessoirement, tu peux avantageusement remplacer /home/gd/result.txt par $HOME/result.txt (voire $HOME/tmp/result.txt afin ce qui a le double avantage de ne pas polluer ton home et de mettre les fichiers temporaires dans le dossier adéquat)
    Et rm -f fichier remplace rm fichier 2>/dev/null...

    Citation Envoyé par disedorgue Voir le message
    Une méthode pour éviter eval pour un tableau à 2 dimensions:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ XX=${tab[1]}[3]
    $ echo ${!XX}
    value4
    Joli J'avais complètement oublié ce ${!var} qui génère une indirection sur $var
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    toto=123
    var=toto
    echo $var => toto
    echo ${!var} => 123
    eval echo \$$var => 123
    Ceci dit, je m'en sers tellement souvent...


    PS: arrêtez d'avoir peur de eval. eval est un outil qui a été fait dans un but précis. Comme tout outil, il peut être bien ou mal utilisé, et donc donner de grandes choses ou bien planter le script. Mais ce n'est certainement pas sa faute si le script plante...
    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]

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 42
    Par défaut
    Voila ce que j'ai. En début de chaque ligne, j'ai le nom de l'hote puis les items (leur id) avec la valeur associé.

    srvstit015;23997 = 100.0000;24005 = 0.0000;24000 = 0.0000;24001 = 0.0167;24006 = 0.0000;24003 = 0.0000;24002 = 0.0750;24007 = 0.0000;
    srvstit012;24047 = 0.0000;24043 = 0.5510;24042 = 0.0083;24048 = 0.0000;24046 = 0.0668;24040 = 93.1201;24041 = 6.0857;24044 = 0.1586;
    srvstit017;24088 = 0.0000;24084 = 0.0754;24081 = 99.8576;24083 = 0.0251;24085 = 0.0000;24079 = 100.0000;24087 = 0.0335;24082 = 0.0084;
    ;
    Je n'en suis pas encore la, mais dans ma fonction zbx_get_item, je parse pour garder la valeur de l'item_id qui me sers pour récupérer la valeur dans la fonction zbx_get_history.
    J'ai mis en rouge pour que vous compreniez: tout les item_id en rouge correspondent à un nom d'item( ex: % d'utilisation). il faudrait que je fasse un tableau de correspondance pour le remplacement, je ne sais pas si c'est possible?

    ce qui doit me donner.

    serveur;utilisation
    srvstit015;100.0000
    srvstit012;0.0000
    Je brule peut etre les étapes, peut etre que je dois faire un tableau de correspondance avant.

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

    Informations forums :
    Inscription : Février 2008
    Messages : 7 660
    Par défaut
    e dois récupérer des données sous zabbix et les mettre sous la forme d'un fichier csv
    donc, tu n'as pas l'intention de te référer aux éléments du tableau ultérieurement !?
    donc, un tableau multi-dimensionnel n'est pas utile.

    la sortie d'une commande ne devrait pas être "envoyée" dans un tableau, ni/puis être lu dans une boucle for, mais être parcourue, comme un fichier, par une boucle while.

    Voila mon script, ma fontion login me permet d'avoir accès au serveur zabbix. Ma fonction host me permet de récupérer tt les noms d'hotes. Ma fonction item me donne les items des hotes. la fonction history me donne la valeur des items.
    Ensuite j'ai fait des boucles. Mais le résultat n'est pas exploitable du tout. (j'ai mis une sortie en txt pour visualiser)
    le résultat n'est pas exploitable du tout
    pourquoi ?

    dans tes fonctions
    • l'emploi d'une variable intermédiaire n'est pas utile : tu peux piper curl vers awk directement
    • awk | cut : c'est pas top [codeinline]awk peut s'occuper du formatage, et n'afficher que les données pertinentes


    je ne tiens pas compte ici de ton dernier message.
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  9. #9
    Expert confirmé Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 349
    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 349
    Par défaut
    Bonjour,

    Citation Envoyé par Sve@r Voir le message
    Bonjour

    Le shell est un langage très très basique. Le Bourne Shell ne connaissait même pas les tableaux. Ceux-ci sont arrivés avec bash mais ils sont limités à une dimension.

    Alors effectivement, on peut utiliser eval afin de "simuler" deux dimensions. On construit d'abord l'expression voulue en utilisant la première dimension du tableau puis eval l'évalue et renvoie l'élément de la seconde dimension

    Exemple
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ serveur=(item1 item2 item3 item4 item5)
    $ toto=(value1 value2 value3 value4 value5)
    $ tata=(value6 value7 value8 value9 value10)
    $ tab=(serveur toto tata)
    $ eval "echo \${${tab[1]}[3]}"
    value4

    Explication: la valeur "value4" se trouve dans toto[3]. Et la chaine "toto" se trouve dans tab[1]. Donc en partant de tab[1] et en rajoutant [3] et des accolades au bon endroit, on arrivera à la valeur voulue.
    Et donc:
    • echo "${tab[1]}" affiche "toto"
    • echo "${tab[1]}[3]" affiche "toto[3]"
    • echo "\${${tab[1]}[3]}" affiche "${toto[3]}"
    • et pour finir, eval "echo \${${tab[1]}[3]}" évalue l'instruction echo ${toto[3]}. Cette instruction est alors évaluée et exécutée comme si elle avait été tapée dans le script et renvoie donc la valeur de "toto[3]" c'est à dire "value4"


    On peut faire de même pour simuler 3, 4, 5, x dimensions. On rajoute des eval de eval autant qu'il faut (mais ça devient vite illisible)...
    Une méthode pour éviter eval pour un tableau à 2 dimensions:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ XX=${tab[1]}[3]
    $ echo ${!XX}
    value4

  10. #10
    Modérateur
    Avatar de jlliagre
    Homme Profil pro
    Ingénieur support avancé & développement
    Inscrit en
    Juin 2007
    Messages
    2 695
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur support avancé & développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 695
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Le Bourne Shell ne connaissait même pas les tableaux. Ceux-ci sont arrivés avec bash mais ils sont limités à une dimension.
    Rendons à César ce qui appartient à César:
    Les tableaux ont été supportés par bash à partir de la version 2.0 en 1996 mais c'est ksh qui, en 1988, a introduit les tableaux standard à un shell de type Bourne puis les tableaux associatifs en 1993. Les tableaux existaient déjà depuis au moins 1980 dans le C shell, mais csh n'est pas un shell de type Bourne.

  11. #11
    Rédacteur

    Avatar de ok.Idriss
    Homme Profil pro
    IS Consultant
    Inscrit en
    Février 2009
    Messages
    5 220
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : IS Consultant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2009
    Messages : 5 220
    Par défaut
    Bonjour.

    Citation Envoyé par Sve@r
    Oui, je viens du Bourne Shell et j'ai la (mauvaise?) habitude de toujours essayer d'écrire mes scripts compatibles. Je sens bien que c'est de moins en moins utile (vu le large épanouissement du bash) mais c'est le problème de l'habitude...
    Je ne dirais pas que c'est une mauvaise habitude, mais je pense aussi que c'est de moins en moins utile aujourd'hui, ça avait du sens à une époque.

    Pour moi se limiter à rendre ses scripts full POSIX-compliant c'est d'une part considérer que les syntaxes Bash rentrent dans la catégorie du "développement sur plateformes spécifiques et exotiques" (alors que c'est le shell qui est très largement le plus utilisé à l'heure actuelle) et d'autre part, se priver de bien des avantages sans avoir une raison valable. Toutes les archis sur lesquelles j'ai bossé sont déployées sur des serveurs Linux (RHEL/CentOS ou Debian/Ubuntu Server), une fois j'ai croisé des HP-UX qui se faisaient remplacés par des CentOS. Bon je sais que c'est pas la même chose pour tout le monde, mais moi à titre personnel j'ai pas de raisons de m'en priver pour l'instant . En plus comme tu le dit, même les versions d'Unix modernes se mettent au bash (ou à minima au KSH).

    Bref, je dirais pas que c'est une mauvaise pratique mais qu'il faut être pragmatique et ne pas limiter tout le monde pour un besoin particulier qui devient de plus en plus rare. Ça n'empêche pas qu'il est toujours intéressant d'avoir plusieurs solutions à un problème dont une solution POSIX compliant.

    Cordialement,
    Idriss

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    42
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 42
    Par défaut
    Merci pour vos réponse

    En faites, je vais devoir remplacer les item ID par leur nom. Et plusieurs ID peuvent avoir le même nom d'item donc la même colonne.
    D'ou l'idée de faire une table de correspondance.

    Comme dit précédemennt, je suis obligé d'utiliser l'item ID pour récupérer la valeur. Je ne peux pas utiliser directement le nom(vu qu'il est commun à plusieurs serveur)

  13. #13
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 835
    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 835
    Billets dans le blog
    1
    Par défaut
    Mouais. Ca devient un peu flou là. "Alors c'est comme je vous ai montrés mais ça peut changer et ..." !!!
    Tant que tu ne nous mettras pas un exemple exhaustif de ce que tu as en entrée et de ce que tu veux en sortie, on ne pourra pas faire mieux...
    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]

Discussions similaires

  1. [Tableaux] tri de tableau deux dimensions
    Par oursquetaire dans le forum Langage
    Réponses: 8
    Dernier message: 27/12/2005, 14h27
  2. Affichage d'un tableau à deux dimensions.
    Par Allan dans le forum C
    Réponses: 3
    Dernier message: 11/12/2005, 18h29
  3. Réponses: 1
    Dernier message: 18/11/2005, 11h38
  4. tri alphabétique dans un tableau deux dimensions
    Par *!!cocco!!* dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 06/12/2004, 21h38
  5. Passage d'un tableau à deux dimensions
    Par karl3i dans le forum C
    Réponses: 3
    Dernier message: 20/10/2003, 14h50

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