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 :

[SHELL]Question délicate sur une boucle


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
    Août 2006
    Messages
    37
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 37
    Par défaut [SHELL]Question délicate sur une boucle
    Bonjour à tous!

    Ma question est la suivante: je dois exécuter une commande sqlplus en "boucle" pour appeler une procédure stockée avec deux params issus d'un fichier csv.

    Le résultat auquel j'arrive est le suivant:
    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
     
    ORACLE_SID=MYBASE;
    export ORACLE_SID;
     
    for enreg in `cat $MYTMPPATH/$MYFILETOPARSE`
    do
        OLDVAL=`echo $enreg | awk -F";" '{ print $1 }'`;
        NEWVAL=`echo $enreg | awk -F";" '{ print $2 }'`;
        OLDVAL="'"$OLDVAL"'"
        NEWVAL="'"$NEWVAL"'"
        $ORACLE_HOME/bin/sqlplus -L monID/MonMDP >> $MYFILELOG
        set serveroutput on;
        whenever sqlerror exit 1 rollback;
        whenever oserror exit 1 rollback;
        exec P2300_integ_csv(${OLDVAL},${NEWVAL});
        commit;
        exit;
    done
    Globalement:
    1) Je ne suis pas très "satisfait", parce qu'il y a un souci sur le "exit" (qui permet de quitter le sqlplus), mais qui quitte l'exécution.
    2) Je pense que je devrais sortir l'exécution de sqlplus du "do" pour l'ouvrir une fois pour toute... Mais je n'y parviens pas.
    3) Mon PLUS GROS souci, c'est qu'au final, le script ne fonctionne pas sur le exec. JE ne vois pas du tout pourquoi.

    sinon, pour les commandes awk, ça je suis certain que ça fonctionne, puisque j'ai testé sans la partie SQL, et j'ai affiché le contenu de mes variables OLDVAL et NEWVAL sans souci.

    Si quelqu'un a une solution ou des indices à me filer... je suis preneur.

    Sinon, j'ai un autre souci débile: j'ai un log dans lequel je veux piocher des lignes comme suit:
    [plein de txt variable en lg][texte à lg variable à récup]
    Schématiquement, je dois donc prendre toute la partie droite d'une ligne, à partir d'un point de texte identifié. Typiquement, ça donnerait un truc
    [citation]SQL>Test valeur toto Erreur: donnée non conforme[/citation]
    et je veux exporter uniquement
    [citation]Erreur: donnée non conforme[/citation]
    j'utilise, en test, ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    awk '/UPDATE/ {print $5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18}' $MYFILELOG > $MYPATH/$MYFILEROLLBACK
    C'est crade, mais pour les tests ça fonctionne.
    Quelqu'un a aussi une solution sur cet aspect?

    En tout cas, toute proposition est bienvenue

  2. #2
    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 magellan94 Voir le message
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        $ORACLE_HOME/bin/sqlplus -L monID/MonMDP >> $MYFILELOG
        set serveroutput on;
        whenever sqlerror exit 1 rollback;
        whenever oserror exit 1 rollback;
        exec P2300_integ_csv(${OLDVAL},${NEWVAL});
        commit;
        exit;
    Globalement:
    1) Je ne suis pas très "satisfait", parce qu'il y a un souci sur le "exit" (qui permet de quitter le sqlplus), mais qui quitte l'exécution.
    Salut
    Effectivement, tout ce qui est entre le "$ORACLE" et le "exit" est (probablement) des commandes qui doivent être traitées par sqlplus. Mais comme tu n'as pas utilisé la bonne syntaxe pour cela, elles sont traitées par le shell.

    Lorsque tu veux faire assimiler tout un code par une commande X dans ton shell, tu as 2 possibilités
    1) echo "tout le code" | commandeX
    Ce qui donnerait dans ton cas
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    (
        echo "set serveroutput on;"
        echo "whenever sqlerror exit 1 rollback;"
        echo "whenever oserror exit 1 rollback;"
        echo "exec P2300_integ_csv(${OLDVAL},${NEWVAL});"
        echo "commit;"
        echo "exit;"
    ) | $ORACLE_HOME/bin/sqlplus -L monID/MonMDP >> $MYFILELOG
    Tu remarques les parenthèses (...) permettant de faire un "groupe de commandes" et d'envoyer tout le groupe dans le pipe...

    2) lancer la commande avec double redirection entrée "<<" plus un flag (moi j'utilise "_EOT_" comme "End Of Text") indiquant au shell où s'arrêter
    A ce moment là, tout ce qui se trouve après la commande sera considéré comme entrée standard de la commande. Et lorsque le shell arrive au flag (qui doit être seul mot de la ligne), il termine alors de traiter les lignes comme data pour la commande et reprend son fonctionnement normal

    Dans ton cas, ce serait
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $ORACLE_HOME/bin/sqlplus -L monID/MonMDP << _EOT_  >> $MYFILELOG
    set serveroutput on;
    whenever sqlerror exit 1 rollback;
    whenever oserror exit 1 rollback;
    exec P2300_integ_csv(${OLDVAL},${NEWVAL});
    commit;
    exit;
    _EOT_

    Accessoirement, je ne suis pas certain que l'ordre "exit" soit nécessaire. Il est sûrement nécessaire dans sqlplus quand tu le lances en interactif (pour quitter sqlplus) mais lancé en mode automatique, il doit probablement quitter tout seul quand il n'a plus rien à avaler (en tout cas c'est comme ça pour les commandes mysql et psql)

    Citation Envoyé par magellan94 Voir le message
    3) Mon PLUS GROS souci, c'est qu'au final, le script ne fonctionne pas sur le exec. JE ne vois pas du tout pourquoi.
    Là je ne vois pas trop ce qui devrait se passer...

    Citation Envoyé par magellan94 Voir le message
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    OLDVAL="'"$OLDVAL"'"
    NEWVAL="'"$NEWVAL"'"
    Pourquoi déquotter les variables ? Les quottes doubles savent gérer une variable
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    OLDVAL="'$OLDVAL'"
    NEWVAL="'$NEWVAL'"

    Citation Envoyé par magellan94 Voir le message
    Sinon, j'ai un autre souci débile: j'ai un log dans lequel je veux piocher des lignes comme suit:
    [plein de txt variable en lg][texte à lg variable à récup]
    Schématiquement, je dois donc prendre toute la partie droite d'une ligne, à partir d'un point de texte identifié. Typiquement, ça donnerait un truc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SQL>Test valeur toto Erreur: donnée non conforme
    et je veux exporter uniquement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Erreur: donnée non conforme
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    echo "ta ligne" |sed -e "s/^.\{1,\}Erreur/Erreur/g"

    Citation Envoyé par magellan94 Voir le message
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    awk '/UPDATE/ {print $5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18}' $MYFILELOG > $MYPATH/$MYFILEROLLBACK
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    awk '/UPDATE/ {for (i=5; i <= 18; i++) printf("%s ", $i); print}' $MYFILELOG > $MYPATH/$MYFILEROLLBACK
    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]

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Août 2006
    Messages
    37
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 37
    Par défaut
    Impeccable!

    Etant novice sur le shell script, je découvre donc au fur et à mesure.

    Pour le coup des "echo", je comprends mieux le pourquoi. A partir de là, je vais peut-être optimiser, mais pour le moment c'est NICKEL!

    Merci encore.

    La seule chose que j'ai du mal à saisir, c'est la commande sed, mais je dois lire la doc pour en comprendre les subtilités concernant sa syntaxe!

    Encore merci, j'ai pu en valider une énorme partie en tout cas.

    au plaisir!

  4. #4
    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 magellan94 Voir le message
    Pour le coup des "echo", je comprends mieux le pourquoi. A partir de là, je vais peut-être optimiser, mais pour le moment c'est NICKEL!
    Quand il y en a beaucoup ça peut être chiant. Dans un cas comme le tien, moi j'aurais utilisé la solution n° 2...

    Citation Envoyé par magellan94 Voir le message
    La seule chose que j'ai du mal à saisir, c'est la commande sed, mais je dois lire la doc pour en comprendre les subtilités concernant sa syntaxe!
    Bah, suffit de demander.
    sed (Stream EDitor) est un éditeur de flux. Il est basé sur "ed" (le tout premier éditeur Unix sur lequel est aussi basé "vi") dont il reprend les possibilités et fonctions mais au lieu d'éditer un fichier, il édite un flot de datas (flot arrivant ici par l'intermédiaire du echo) et renvoie ensuite (comme toute commande) les infos à l'écran (infos que tu peux alors capturer, comme tu le fais déjà dans tes commandes awk, avec les backquottes => var=`echo ... |sed ...`)

    Donc j'utilise sed pour modifier en live ta ligne de log. L'idée est de traiter un flot X selon ses caractéristiques générales pour avoir en sortie une data Y. Et la caractéristique que j'utilise est le mot clef "Erreur" (c'est pas super rigoureux parce que si le mot se trouve plusieurs fois sur la ligne ça va merdouiller mais j'ai pas trouvé mieux).
    Je demande donc à sed d'effectuer un remplacement d'une chaine X par une chaine Y (s/chaineX/chaineY/). La chaine X sera composée de tout caractère (.) en partant du début de ligne (^) répété 1 ou plusieurs fois ({1,}) suivi de la chaine "Erreur". La chaine Y sera simplement "Erreur". Bref ça supprime simplement tout ce qu'il y a avant "Erreur" sur la ligne. Le "g" final est d'ailleurs de trop (je l'ai tapé par réflexe car il signifie "répéter l'action si la chaine X se trouve plusieurs fois sur la ligne" ce qui ne se peut pas ici).

    Et la syntaxe exprimée pour représenter la chaine X cherchée n'est pas spécifiquement liée à sed mais aux expressions régulières (regex). Il s'agit d'une grammaire connue de beaucoup d'outils Unix permettant de spécifier un motif cherché selon diverses caractéristiques qui peuvent aller très loin dans la complexité (il existe des bouquins spécialisés sur les regex)
    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]

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Août 2006
    Messages
    37
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 37
    Par défaut
    Merci pour toutes ces précisions. Cela confirme ce que je pensais dès le départ,à savoir qu'il me manque surtout des notions sur le comportement de l'exécution des scripts... De là, je crois qu'il me faudra m'envoyer un paquet de documentations histoire de bien tout saisir.

    En tout cas, tout ce que tu m'as déjà précisé est copié/collé dans un coin de ma doc perso, et je vais probablement en placer une partie dans un wiki pro où je bosse (hé oui: ça aide de trouver des gens compétents)


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

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

    sans oublier : comment parser un fichier

    j'ai un autre souci
    normalement, autre souci = autre sujet
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

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

Discussions similaires

  1. [PPT-2010] Questions sur une boucle
    Par droopy1702 dans le forum Powerpoint
    Réponses: 2
    Dernier message: 03/02/2014, 10h08
  2. question sur une boucle et un break
    Par isidore dans le forum C
    Réponses: 10
    Dernier message: 22/11/2006, 20h26
  3. Réponses: 11
    Dernier message: 19/06/2006, 16h54
  4. Question rapide sur une requette simple
    Par batoubat dans le forum Requêtes
    Réponses: 3
    Dernier message: 12/06/2006, 18h39
  5. Problème sur une boucle
    Par Mateache dans le forum ASP
    Réponses: 6
    Dernier message: 31/01/2006, 09h48

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