Comparaison des versions

Légende

  • Ces lignes ont été ajoutées. Ce mot a été ajouté.
  • Ces lignes ont été supprimées. Ce mot a été supprimé.
  • La mise en forme a été modifiée.

...

Voici donc une proposition de code python qui permet de faire cette jonction.

 

Bloc de code
languagepy
titlejoin_files.py
linenumberstrue
#!/usr/bin/python
# -*- coding: utf-8 -*-

# si python < 3
from __future__ import print_function

usage = """
[usage] %s --table1 <fichier tableau CSV1> --table2 <fichier tableau CSV2> --jointable <fichier jointure tableau CSV> --sep <séparateur de champs> --format <format affichage des données à afficher avec %s pour chaque colonne à afficher> --colonnes <couples numéro de fichier (1 ou 2) «.» numéros de colonnes pour chaque %s du format donné précédemment ; séparés par des «,»>

Ce script a pour but de faire une jointure entre 3 fichiers :

- Un permier contenant une liste (genre CSV) séparée par un séparateur
(par défaut «|») avec plusieurs champs dont le premier est
l'identifiant unique (ou alors un autre numéro de colonne considérée
comme contenant l'identifiant).

- Un deuxième contenant une liste (genre CSV) séparée par un
séparateur (par défaut «|») avec plusieurs autres champs et entrées
dont le premier (par défaut) est l'identifiant unique. On peut
également donner un numéro de colonne pour cet identifiant.

- un troisième fichier contenant au moins deux colonnes avec, dans le
premier champ (séparateur = «|»), une liste d'identifiants
correspondants au premier fichier (on peut aussi donner un numéro de
colonne si ce n'est pas la première — valeur par défaut).et le
deuxième champ correspondant à l'identifiant du deuxième fichier (avec
un séparateur = «|» par défaut) et un numéro de colonne = 2 par défaut
mais qui peut être précisé.

Les numéros de colonnes commencent à 1.

"""


import sys
import os
from optparse import OptionParser

# traitement des options

parser = OptionParser(usage)
parser.add_option("--table1", dest="ftable1",
                  help="Tableau CSV 1")
parser.add_option("--colonne_id1", dest="ct1", default=1, type="int",
                  help="Numero de colonne de l'identifiant du premier tableau CSV")
parser.add_option("--table2", dest="ftable2",
                  help="Tableau CSV 2")
parser.add_option("--colonne_id2", dest="ct2", default=1, type="int",
                  help="Numero de colonne de l'identifiant du deuxieme tableau CSV")
parser.add_option("--jointable", dest="fjointable",
                  help="Tableau CSV contenant les identifiants uniques des 2 tableaux CSV 1 et 2")
parser.add_option("--colonne_jid1", dest="cj1", default=1, type="int",
                  help="Numero de colonne de l'identifiant du premier tableau CSV dans le fichier de jointure (le troisieme fichier)")
parser.add_option("--colonne_jid2", dest="cj2", default=2, type="int",
                  help="Numero de colonne de l'identifiant du deuxieme tableau CSV dans le fichier de jointure (le troisieme fichier)")
parser)")
parser.add_option("--sep", dest="sep", default="|",
                  help="Separateur utilise pour tous les fichiers-tableaux CSV - un seul caractere attendu - valeur par defaut le pipe")
#parser.add_option("--sep1", dest="sep1",
#                  help="Separateur utilise pour le fichiers-tableaux CSV 1 - un seul caractere attendu - pas de valeur par defaut")
#parser.add_option("--sep2", dest="sep2",
#                  help="Separateur utilise pour le fichiers-tableaux CSV 2 - un seul caractere attendu - pas de valeur par defaut")
#parser.add_option("--sepsepj12", dest="sep", default="|"sepj12",
#                  help="Separateur utilise pour tousle les fichiers-tableaux CSV de jointure - un seul caractere attendu - pas de valeur par defaut le pipe")
parser.add_option("--format", dest="format",
                  help="Format avec des %s le ou seront les donnees reprises des colonnes des deux tableaux CSV")
parser.add_option("--colonnes", dest="colonnes",
                  help="Couples numero de fichier (1 ou 2) '.' numeros de colonnes pour chaque %s du format donne precedemment; separes par des ','")
(options, args) = parser.parse_args()

#if len(args) <= 6:
#    parser.error("Incorrect number of arguments")
#    parser.error(usage % sys.argv[0])
#    sys.exit(2)

t1 = {} # tableau de hashage contenant les enregistrements du premier fichier-tableau avec la colonne identifiant unique comme clé
t2 = {} # tableau de hashage contenant les enregistrements du deuxième fichier-tableau avec la colonne identifiant unique comme clé

sep = options.sep # le séparateur utilisé
ct1 = options.ct1 - 1 # le numéro de colonne contenant l'identifiant unique du premier tableau du premier fichier
ct2 = options.ct2 - 1 # le numéro de colonne contenant l'identifiant unique du second tableau du deuxième fichier
cj1 = options.cj1 - 1 # le numéro de colonne contenant l'identifiant unique du premier tableau dans le troisième fichier, fichier de jonction entre les deux premiers
cj2 = options.cj2 - 1 # le numéro de colonne contenant l'identifiant unique du second tableau dans le troisième fichier, fichier de jonction entre les deux premiers

with open(options.ftable1, 'r') as table1:
    for ligne in table1:
        ligne = ligne.rstrip()
        tl1 = ligne.split(sep)
        if len(tl1) <= ct1:
            print("[Erreur] Le numéro de colonne de l'identifiant du tableau CSV 1 dépasse le nombre de colonne de la ligne: %d pour %d max colonnes" % (ct1, len(tl1)), file=sys.stderr)
            continue
        id1 = tl1[ct1]
        t1[id1] = tl1

with open(options.ftable2, 'r') as table2:
    for ligne in table2:
        ligne = ligne.rstrip()
        tl2 = ligne.split(sep)
        if len(tl2) <= ct2:
            print("[Erreur] Le numéro de colonne de l'identifiant du tableau CSV 2 dépasse le nombre de colonne de la ligne: %d pour %d max colonnes" % (ct2, len(tl2)), file=sys.stderr)
            continue
        id2 = tl2[ct2]
        t2[id2] = tl2

with open(options.fjointable, 'r') as jointure_t12:
    for ligne in jointure_t12:
        ligne = ligne.rstrip()
        jt12 = ligne.split(sep)
        if len(jt12) <= cj1 or len(jt12) <= cj2:
            print("[Erreur] Le numéro de colonne de l'identifiant du tableau de jointure dépasse le nombre de colonne de la ligne: %d (identifiant tableau1) - %d (identifiant tableau2) - pour %d max colonnes" % (cj1, cj2, len(jt12)), file=sys.stderr)
            continue
        jid1 = jt12[cj1]
        jid2 = jt12[cj2]
        try:
            tableau_a_afficher = []
            for i in options.colonnes.split(","):
                (filenumber, colnumber) = i.split(".")
                if int(filenumber) == 1:
                    # on enlève 1 au numéro de colonne car ce numéro commence à 1 contrairement aux tableaux python
                     tableautableau_a_afficher.append(t1[jid1][int(colnumber) - 1])
                elif int(filenumber) == 2:
                    tableau_a_afficher.append(t2[jid2][int(colnumber) - 1])
            # pour que le format d'affichage (tableau_a_afficher) soit interprété correctement par print,
            # il faut que ce soit un tuble et nom un tableau.
            print(options.format % tuple(tableau_a_afficher))
        except KeyError as k:
            print("Erreur de clé pour jid1 %s- jid2 %s" % (jid1, jid2), file=sys.stderr)
            continue

Exemple d'utilisation

Bloc de code
languagebash
titleUtilisation
# dump de la base de donnée centreon sous forme d'un ensemble de fichiers sql contenant la description sql de la création de ces tables
# et de fichiers txt contenant le dump des données de ces tables sous un format CSV (séparateur = «|»)
mkdir -p /tmp/Sauvegardes/centreon
mysqldump -u root --quick centreon --tab=/tmp/Sauvegardes/centreon --fields-terminated-by="|" -c

# insertion des contactgroups
# il faut avoir installé les clapi de centreon pour que ça fonctionne
cd /tmp/Sauvegardes/centreon
cut -d"|" -f 2,3 contactgroup.txt \
  | perl -e 'while(<>) { chomp; ($name, $alias) = split(/\|/); print "centreon -u admin -p ************ -o CG -a add -v \"$name;$alias\"\n"; }' | bash

# et maintenant, la partie qui nous intéresse avec l'utilisation de join_files.py
/usr/local/bin/join_files.py --table1 /tmp/Sauvegardes/centreon/contact.txt \
                             --table2 /tmp/Sauvegardes/centreon/contactgroup.txt \
                             --jointable /tmp/Sauvegardes/centreon/contactgroup_contact_relation.txt \
                             --sep "|" \
                             --colonne_id1 1 \
                             --colonne_id2 1 \
                             --colonne_jid1 2 \
                             --colonne_jid2 3 \
                             --format 'centreon -u admin -p ************* -o CG -a addcontact -v "%s;%s"' \
                             --colonnes '2.2,1.4'
# car la colonne 2 du fichier des contactgroups contient le nom du contactgroup qu'il faut alimenter par le nom du contact donné dans la 4ième colonne de «contact.txt».
# le tableau CSV de jointure (contactgroup_contact_relation.txt) contient 3 champs dont
# le 2ième contient l'identifiant du tableau des contacts et le 3ième qui contient l'identifiant du tableau des contactgroups.

...