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

  1. #1
    Membre à l'essai
    Récupérer résultat d'une réquête dans un tableau en shell (ksh)
    Bonjour,

    Je me permets de faire appel aux développeurs (je ne le fais qu'en appoint...)

    Je fais un script shell (ksh).

    Cela pourrait très bien être une requête sql via sqlplus, même s'il s'agit ici d'une requête Hive, ça ne change pas ma question.

    Je veux récupérer par une requête Hive (via beeline) 2 colonnes d'une table dans un tableau.
    Je fais :

    RESULTAT_REQUETE=`beeline [...] --showHeader=false --outputformat=csv2 -e "select colonnne1,colonnne2 from ma_table;"`

    Cela me donne les bonne données mais en 1 seule variable d'une seule ligne et colonne.

    Or, je voudrais que ça me rende un tableau à 2 dimensions (à envoyer par mail) du type :

    colonne1 colonne2
    toto 5
    titi 3
    tata 7

    Pourriez- vous m'indiquer comment faire, svp ?

    Merci par avance !

  2. #2
    Expert éminent sénior
    Bonjour

    "D'une seule ligne" ? Je ne pense pas. Je pense plutôt que tu l'as mal affichée.

    Quoi qu'il en soit, il suffit d'enlever la substitution de commande. N'est-ce pas ? D'ailleurs, entre nous, utiliser les `backtics` est suranné, obsolète, dépassé, à mettre à la poubelle. On utilise $( ).

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    beeline [...] --showHeader=false --outputformat=csv2 -e "select colonnne1,colonnne2 from ma_table;"
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  3. #3
    Membre à l'essai
    Bonjour Flodelarab,

    Merci d'avoir répondu.

    La commande beeline seule fonctionne bien en effet, et me donne les 3 lignes attendues.
    Mais j'ai besoin de récupérer le résultat dans une variable.
    Et d'utiliser par exemple la 2ème colonne de la 1ère ligne du résultat.

    Donc enlever les `backtics` ou $( ) et la variable ne résout pas mon problème.

    Avez-vous une solution ?

    Merci !

  4. #4
    Expert éminent sénior
    Vouloir tout mettre dans une variable comme dans les langages de programmation à pointeurs (comme C++, java, ...) n'est pas une bonne idée. La sortie d'une commande est un fichier texte. Et pour éviter les fichiers temporaires, en shell, on utilise des conduites (pipes en anglais). Le résultat de la première commande sert de fichier d'entrée de la seconde commande.

    utiliser par exemple la 2ème colonne de la 1ère ligne du résultat.
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    beeline [...] --showHeader=false --outputformat=csv2 -e "select colonnne1,colonnne2 from ma_table;" | awk '(NR==1){print $2;}'


    Un exemple concret factice :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    { echo "Toto Tata Titi Tutu"; echo "Zozo zizi zaza zuzu"; echo "Popo papa pipi pupu";}
    Toto Tata Titi Tutu
    Zozo zizi zaza zuzu
    Popo papa pipi pupu


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    { echo "Toto Tata Titi Tutu"; echo "Zozo zizi zaza zuzu"; echo "Popo papa pipi pupu";} | awk '(NR==1){print $2;}'
    Tata


    Si le séparateur de champs, dans chaque ligne, n'est pas l'espace, tu peux le spécifier par l'option -F.

    Il existe des tas d'outils pour t'aider à reformater tes données. Reste à savoir le vrai but final.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  5. #5
    Membre à l'essai
    Merci Flodelarab de ton retour.

    Ah OK donc si je comprends bien, on ne peux pas utiliser de tableaux tab[i] ou tab[i,j] ?

    Je vais être plus précis sur mon besoin en utilisant un exemple factice également.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select nom,count(*) from clients where nom in ${liste_clients};
    Toto,2
    Tata,0
    Titi,1


    Puis en fonction du count(*), s'il est différent de 0, on indique Présent, et s'il est égal à 0, on indique absent, afin d'avoir un tableau du type :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    Toto : Présent
    Tata : Absent
    Titi : Présent


    Merci par avance !

  6. #6
    Expert éminent sénior
    Ah OK donc si je comprends bien, on ne peux pas utiliser de tableaux tab[i] ou tab[i,j] ?
    tab[i] oui.
    tab[i,j] non.


    Je vais être plus précis sur mon besoin en utilisant un exemple factice également.
    L'exemple que tu prends s'appelle un fichier CSV (comma separated values = valeurs séparées par une virgule). C'est souvent ce qui tient lieu de tableau bidimensionnel en shell. Même si le séparateur n'est pas toujours la virgule.

    Puis en fonction du count(*), s'il est différent de 0, on indique Présent, et s'il est égal à 0, on indique absent, afin d'avoir un tableau du type :
    awk est le bon outil pour des fichiers csv.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ awk -F, '($2>0){print $1,"Présent";} ($2==0){print $1,"Absent";}' fichier.txt
    Toto Présent
    Tata Absent
    Titi Présent

    Ou avec un opérateur ternaire :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ awk -F, '{print $1, (($2>0)?"Présent":"Absent");}' fichier.txt
    Toto Présent
    Tata Absent
    Titi Présent


    Dans ton retraitement de requête :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    ./ma_requête_BDD.ksh | awk -F, '{print $1, (($2>0)?"Présent":"Absent");}'
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  7. #7
    Membre à l'essai
    Merci Flodelarab pour toute ton aide, c'est vraiment gentil !

    J'avoue que ça fait des années que j'ai pas fait de awk, je n'aurais pas trouvé le (($2>0)?...) ;-) !

    Merci encore, je vais tester tout ça.

    Bonne journée.

  8. #8
    Membre à l'essai
    Et si tu as en plus un truc simple pour l'envoyer dans un beau tableau par mail, n'hésite pas ;-)
    Mais je dois pouvoir trouver ça ailleurs je pense, plus facilement.
    Pas comme ce que tu m'as débloqué !
    Merci encore !

  9. #9
    Expert éminent sénior
    Si tu peux envoyer des courriers, il suffit de mettre la commande dans la conduite.

    Un truc du genre :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    ./ma_requête_BDD.ksh | awk -F, '{print $1, (($2>0)?"Présent":"Absent");}' | mail -s "Bilan absence/présence" -a - "adresse.destinataire@servermail.fr"

    Le tiret après "-a" veut dire que la pièce jointe est celle qui vient de l'entrée standard, donc de la conduite (pipe).
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  10. #10
    Membre à l'essai
    Je résume, pour celui qui viendrait chercher de l'aide ici s'il était perdu comme moi avant l'aide de Flodelarab, en reprenant nos exemples factices (pour info je dois utiliser sendmail et non mail) ^^.
    Et en ajoutant à la fin une dernière question ;-)

    J'ai 2 scripts :

    - le script ma_requête_BDD.ksh contenant la requête :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    #! /bin/ksh
    beeline [...] --showHeader=false --outputformat=csv2 -e "select nom,count(*) from clients where nom in ${liste_clients};


    - le script principal script_principal.ksh qui lance le script de la requête, met le résultat dans le fichier fic_resultat et envoie le mail :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    ./ma_requête_BDD.ksh | awk -F, '{print $1, (($2>0)?"Présent":"Absent");}' > ${fic_resultat}


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    (cat <<EOCAT
    From: expediteur@serveurmail.fr
    To: destinataire@serveurmail.fr
    Subject: Objet du mail
    MIME-Version: 1.0
    Content-Type: text/plain; charset=utf-8
    EOCAT
    cat ${fic_resultat}) | /usr/lib/sendmail "destinataire@serveurmail.fr"


    Pour info :
    Si je mets :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    text/html
    au lieu de
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    text/plain

    Cela m'envoie un mail avec 1 seule ligne au lieu des 4 lignes de mon fichier fic_resultat (car il n'a pas les balises html de passage à la ligne).

    J'ai donc bien ce que je souhaite, à savoir :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Toto Présent
    Tata Absent
    Titi Présent
    Tutu Présent


    Ma dernière étape serait d'envoyer le même résultat mais dans un tableau avec les bordures : est-ce simple ?

    Merci !

  11. #11
    Expert éminent sénior
    Avant, juste un commentaire : la différence entre ( ) et {; } est que les parenthèses créent un sous-processus, ce dont tu n'as pas besoin. Des accolades suffisent. L'accolade ouvrante est considérée comme un mot clé, donc il faut penser à mettre un espace après. Et il faut un saut de ligne ou un point-virgule avant l'accolade fermante. Regarde mon exemple avec les 3 "echo" regroupés.

    Ma dernière étape serait d'envoyer le même résultat mauis dans un tableau avec les bordures : est-ce simple ?
    Tu as déjà répondu à la question. Il faut ajouter les balises html de tableau. Peut-être même les balises complètes d'une page html complète. À voir.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    $ awk -F, 'BEGIN{print "<table border=\"1\" bgcolor=\"ffffcc\" bordercolor=\"ff0000\">";} {print "<tr><td>"$1"</td><td>"(($2>0)?"Présent":"Absent")"</td></tr>";} END{print "</table>";}' fichier.txt
    <table border="1" bgcolor="ffffcc" bordercolor="ff0000">
    <tr><td>Toto</td><td>Présent</td></tr>
    <tr><td>Tata</td><td>Absent</td></tr>
    <tr><td>Titi</td><td>Présent</td></tr>
    </table>




    J'ai mis des couleurs pour exemple. Tu peux changer ou enlever.
    Si tu envoies en texte plein, il n'y a, évidemment, pas de mise en forme.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  12. #12
    Membre à l'essai
    Flodelarab, franchement t'as été parfait, niveau aide et gentillesse !
    Merci sincèrement du temps précieux gagné !

    Tout fonctionne comme je veux.

    Je vais adapter au problème plus général de ce dont j'ai besoin mais j'ai toutes les infos.

    (Juste par rapport aux parenthèses et aux accolades, tu parles de ma partie d'envoi de mail ? du awk ?)

    Merci pour tout Flodelarab !

  13. #13
    Expert éminent sénior
    Tout fonctionne comme je veux.


    (Juste par rapport aux parenthèses et aux accolades, tu parles de ma partie d'envoi de mail ? du awk ?)
    Je parlais du regroupement de commandes, dans la partie shell ksh, juste avant sendmail. Tu regroupes 2 commandes "cat". Mais les parenthèses demandent au système de créer un processus supplémentaire, alors que des accolades resteraient dans le processus du script et laisseraient le système tranquille.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  14. #14
    Membre à l'essai
    Merci !

    Bonne journée.