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

Unix Discussion :

Splitter le résulat d'une requête de sélection dans plusieurs fichiers


Sujet :

Unix

  1. #1
    Membre averti Avatar de danyboy85
    Homme Profil pro
    Développeur Java
    Inscrit en
    Décembre 2005
    Messages
    548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Décembre 2005
    Messages : 548
    Points : 312
    Points
    312
    Par défaut Splitter le résulat d'une requête de sélection dans plusieurs fichiers
    Bonjour,

    Dans un script Shell, j'exécute une requête SQL de sélection à l'aide de la commande "sqlplus".

    Voici le résultat de cette requête :

    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
    [ticket 36]
    InternalMU;CONSTRUCTED;
    InternalMU.contexteAppel;CONSTRUCTED;
    InternalMU.contexteAppel.nature;STRING;GSM
    InternalMU.contexteAppel.codeFermetureCom;STRING;N
    InternalMU.contexteAppel.idPFI;STRING;0
    [ticket 39]
    InternalMU;CONSTRUCTED;
    InternalMU.contexteAppel;CONSTRUCTED;
    InternalMU.contexteAppel.nature;STRING;GSM
    InternalMU.contexteAppel.idPFI;STRING;0
    [ticket 40]
    InternalMU;CONSTRUCTED;
    InternalMU.contexteAppel;CONSTRUCTED;
    InternalMU.contexteAppel.nature;STRING;GSM
    InternalMU.contexteAppel.idPFI;STRING;0
    [ticket 48]
    InternalMU;CONSTRUCTED;
    InternalMU.contexteAppel;CONSTRUCTED;
    InternalMU.contexteAppel.nature;STRING;GSM
    InternalMU.contexteAppel.codeFermetureCom;STRING;N
    InternalMU.contexteAppel.idPFI;STRING;0
    [ticket 63]
    InternalMU;CONSTRUCTED;
    InternalMU.contexteAppel;CONSTRUCTED;
    InternalMU.contexteAppel.nature;STRING;GSM
    InternalMU.contexteAppel.codeFermetureCom;STRING;N
    InternalMU.contexteAppel.idPFI;STRING;0
    Ensuite, j'ai besoin de splitter le résultat dans plusieurs fichiers en fonction de la règle suivant : Au bout de 3 tickets, je change de fichier. Je détecte le début d'un ticket car la ligne commence toujours par [ticket n]

    On m'a conseillé d'utiliser la commande awk, mais je ne sais pas du tout comment l'utiliser donc si quelqu'un sait comment faire...

    Merci d'avance

    Dany
    "Wash me away Clean your body of me Erase all the memories They'll only bring us pain And I've seen All i'll ever need"

  2. #2
    Membre expérimenté Avatar de plxpy
    Homme Profil pro
    Ingénieur géographe
    Inscrit en
    Janvier 2009
    Messages
    792
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur géographe
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Janvier 2009
    Messages : 792
    Points : 1 481
    Points
    1 481
    Par défaut
    C'est assez dur de te répondre sans faire, grosso modo, tout le boulot si tu ne connais pas awk. C'est bien une "commande" mais c'est surtout un interpréteur. Donc apprendre à s'en servir c'est un peu comme apprendre la programmation en shell (le "User's guide" de GNU awk fait 360 pages ...). Comme ton post est resté sans réponse depuis un petit bout de temps, je m'y colle.

    Comme tu ne connais pas awk, je vais rester dans le général et les comportements par défaut. En gros, awk est un processeur de fichiers texte. Il va traiter les lignes, l'une après l'autre, et découper chaque ligne en champs/fields (par défaut, les séparateurs de champs sont les espaces et les tabulations). Dans le script, $0 représente toute la ligne courante, $1,$2,$3, etc... les champs.

    Dans un script awk, tu peux traiter toutes les lignes ou des lignes qui vont "matcher" une expression régulière. Dans ton exemple, on va traiter chaque ligne pour la copier dans un fichier et on va traiter spécifiquement les lignes qui commencent par "[ticket".
    Tu peux aussi avoir une partie "BEGIN" qui est exécutée 1 seule fois avant d'attaquer la première ligne et une partie "END" qui est exécutée 1 seule fois aussi, après le traitement de la dernière ligne.

    Pour que tu vois à quoi ça ressemble, un premier script, avec beaucoup (trop) de commentaires, qui va créer des fichiers "group_1", "group_2", etc... avec à chaque fois le contenu de 3 tickets (sauf peut-être pour le dernier groupe où ça peut aussi être 1 ou 2 tickets).

    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
     
    BEGIN {
        # code execute 1 et 1 seule fois avant de traiter la
        # premiere ligne du fichier en entree. J'y initialise
        # quelques variables
        nb_groups = 1           # nombre de groupes
        nb_tickets = 0          # nombre de tickets
        filename = "group_1"    # nom du premier fichier en sortie
    }
     
    /^\[ticket/ {
     
        # code execute a chaque fois que la ligne courante
        # commence (le '^') par '[ticket'. Comme le '[' peut
        # servir pour definir une expression reguliere, je dois
        # le neutraliser avec un '\' d'ou  /^\[ticket/
     
        if (nb_tickets == 3)
        {
            # on vient de traiter un groupe de 3 tickets et
            # on en attaque un quatrieme
     
            # je ferme le fichier
            close(filename)
            # j'incremente le nombre de groupe
            nb_groups++
            # le nom du nouveau fichier en sortie
            filename = "group_" nb_groups
            # je reinitialise mon nombre de tickets
            nb_tickets = 1
        }
        else
            # je ne fais qu'incrementer le nombre de tickets traites
            nb_tickets++
    }
     
    {
        # code execute pour chaque ligne lue/courante
        print $0 > filename
    }
     
    END {
        # je ferme le dernier fichier cree
        close(filename)
    }

    Si ce script est sauvegardé en "version1.awk" et que ton fichier à traiter s'appelle "source", tu lances, par exemple, "awk -f version.awk source" et tu récupèreras "group_1" et "group_2" dans le répertoire courant


    Pendant que j'y étais, j'ai fait une deuxième version qui crée des fichiers groupes dont le nom reprend les numéros des tickets contenus. Là, tu es obligé de mémoriser les lignes lues car tu dois attendre le dernier ticket pour constituer le nom du fichier en sortie. De cette façon, ça me permet de te montrer comment définir ta propre fonction.

    (On pourrait se contenter de modifier la première version en mémorisant les numéros des tickets et renommer group_1, group_2 mais on est là pour apprendre et voir à quoi ça ressemble)


    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
     
    function process_group(tickets,nb_tickets,lines,nb_lines) {
     
        # fonction a appeler quand on veut creer un fichier
        # avec les differents tickets memorises (3 ou moins (le
        # dernier paquet))
     
     
        # je construis le nom du fichier du groupe a traiter
        # qui comprend les numeros des tickets du groupe
        filename = "group"
        for (t=0;t<nb_tickets;t++)
            filename = filename "_" tickets[t]
     
        # ecriture des lignes des tickets dans le fichier
        for (l=0;l<nb_lines;l++)
            print lines[l] > filename
     
        # fermeture du fichier
        close(filename)
    }
     
     
    BEGIN {
        nb_tickets = nb_lines = 0
    }
     
    /^\[ticket/ {
     
        if (nb_tickets == 3)
        {
            process_group(tickets,nb_tickets,lines,nb_lines)
            nb_tickets = nb_lines = 0
        }
     
        # je memorise le numero du ticket ...
        tickets[nb_tickets] = substr($2,1,length($2)-1)
        # et j'incremente le nombre de tickets traites
        nb_tickets++
    }
     
    {
        # je stocke la ligne courante ...
        lines[nb_lines] = $0
        # et incremente le nombre de lignes
        nb_lines++
    }
     
    END {
        # traitement du dernier groupe a 1, 2 ou 3 tickets
        process_group(tickets,nb_tickets,lines,nb_lines)
    }

    Là aussi, un "awk -f version2.awk source" te créera deux fichiers, ici "group_36_39_40" et "group_48_63"

    Maintenant, tu sais à quoi ça ressemble. Awk est parfois bien utile mais, quand les scripts sont gros, ça peut devenir l'horreur à débuguer. Quant aux messages d'erreurs, ils sont parfois assez "brut de fonderie" et on ne voit pas toujours ce qui cloche.
    "La simplicité ne précède pas la complexité, elle la suit." - Alan J. Perlis
    DVP ? Pensez aux cours et tutos, ainsi qu'à la FAQ !

Discussions similaires

  1. Réponses: 9
    Dernier message: 04/12/2014, 17h26
  2. [Python 3.X] Script modifiant une chaîne de caractères dans plusieurs fichiers.
    Par Julien698 dans le forum Général Python
    Réponses: 4
    Dernier message: 09/09/2014, 13h41
  3. Réponses: 11
    Dernier message: 06/02/2013, 15h25
  4. Rechercher/remplacer une chaine de caractères dans plusieurs fichiers
    Par _shuriken_ dans le forum Shell et commandes GNU
    Réponses: 5
    Dernier message: 31/07/2011, 20h06
  5. Réponses: 0
    Dernier message: 08/06/2009, 13h57

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