Précédent   Forum des professionnels en informatique > Systèmes > Autres systèmes > Unix
Unix Forum d'entraide sur les systèmes Unix et dérivés (*BSD, AIX, etc.). Avant de poster ->F.A.Q BSD F.A.Q. Aix
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 08/06/2009, 14h46   #1
Membre confirmé
 
Avatar de danyboy85
 
Homme Dany G
Développeur Java
Inscription : décembre 2005
Messages : 496
Détails du profil
Informations personnelles :
Nom : Homme Dany G
Âge : 27
Localisation : France, Loire Atlantique (Pays de la Loire)

Informations professionnelles :
Activité : Développeur Java

Informations forums :
Inscription : décembre 2005
Messages : 496
Points : 232
Points : 232
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 :
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"
danyboy85 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/06/2009, 09h17   #2
Membre éclairé
 
Avatar de plxpy
 
Homme
Ingénieur
Inscription : janvier 2009
Messages : 268
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 46
Localisation : France, Haute Garonne (Midi Pyrénées)

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

Informations forums :
Inscription : janvier 2009
Messages : 268
Points : 396
Points : 396
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 :
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 :
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.
plxpy est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +1. Il est actuellement 06h38.


 
 
 
 
Partenaires

Hébergement Web