2010-08-11 6 views
2

J'ai 2 grands fichiers journaux. Je veux voir si un périphérique est dans un mais pas b et vice versa (exclure les lignes où le périphérique est commun) les fichiers ressemblent à cet exemple.python analyser 2 logfiles

04/09/2010,13: 11: 52, Authen OK, utilisateur1, Groupe par défaut, 00-24-2B-A1-08-88,29,10.1.1.1, (Par défaut) ,,,, ,, 13, EAP-TLS ,, dispositif1,
04/19/2010,15: 35: 24, Authen OK, utilisateur2, Groupe par défaut, 00-24-2B-A1-05-EA, 29,10.1.1.2 , (Par défaut) ,,,,,, 13, EAP-TLS, device2,
04/09/2010,13: 11: 52, Authen OK, utilisateur3, Groupe par défaut, 00-24-2B-A1-08 -88,29,10.1.1.3, (Par défaut) ,,,,,, 13, EAP-TLS, device3,
04/19/2010,15: 35: 24, Authen OK, utilisateur4, Groupe par défaut, 00 -24-2B-A1-05-EA, 29,10.1.1.4, (Par défaut) ,,,,,, 13, EAP-TLS, device4,

pour réitérer, j'ai besoin de périphérique (champ [- 2]) et IP (f ield [7]) pour chaque périphérique qui est dans le fichier journal a mais pas b, et qui est dans b mais pas

Voici ce que j'ai fait jusqu'à présent, mais qui semble un peu maladroit et très lent (chaque fichier a environ 400K lignes). Je crois que deux fois. Quelqu'un peut-il suggérer des gains d'efficacité s'il vous plaît? Peut-être que j'utilise la mauvaise logique ??

chst={} 
chbs={} 
for i,line in enumerate(open('chst.txt').readlines()): 
    line=line.split(',') 
    chst[line[-2]+','+str(i)]=','.join(line) 

for i,line in enumerate(open('chbs.txt').readlines()): 
    line=line.split(',') 
    chbs[line[-2]+','+str(i)]='.'.join(line) 

print "these lines are in CHST but not in CHBS" 
for a in chst: 
    if a.split(',')[0] not in str(chbs.values()): 
     line=chst[a].split(',') 
     print line[-2], line[7] 

print "\nthese lines are in CHBS but not in CHST" 

for a in chbs: 
    if a.split(',')[0] not in str(chst.values()): 
     line=chbs[a].split(',') 
     print line[-2], line[7] 

Répondre

1

Vous cherchez un symmetric difference:

chst = { (line.split(",")[ -2 ], line.split(",")[ 7 ]) for line in open(...) } 
chbs = { (line.split(",")[ -2 ], line.split(",")[ 7 ]) for line in open(...) } 

diff = chst^chbs 

Si vous avez besoin des différences asymétriques, utilisez -:

chst - chbs # tuples in chst but not in chbs 
chbs - chst # tuples in chbs but not in chst 

Si vous avez besoin de la ligne réelle, au lieu d'un tuple (device, IP) vous pouvez utiliser des dictionnaires au lieu des ensembles:

chst = { (line.split(",")[ -2 ], line.split(",")[ 7 ]): line for line in open(...) } 
chbs = { (line.split(",")[ -2 ], line.split(",")[ 7 ]): line for line in open(...) } 

diff = chst.items()^bar.items() 

Cela fonctionne car dict.items() renvoie un view sur les éléments, qui a des propriétés setlike. Notez que cela s'appelle dict.viewitems() dans Python 2.x.

+0

Le module sets est obsolète depuis Python 2.6. A partir de 2.6, set et frozensets sont en effet des builtins. –

+0

Oups, l'équipe de backporting * a * été * occupée! Fixé. – katrielalex

+0

Je suis également certain que l'appel d'éléments ne fonctionnera pas (et n'est pas non plus lié aux vues dict) - vous devriez appeler viewitems sur cette dict, supporté en commençant par 2.7. La méthode items renvoie juste une liste de paires clé/valeur, et pour les listes, l'opérateur^n'est pas supporté, tandis que viewitems renvoie une vue réelle de type dict_ietms. –

0

Il ya un bug dans la ligne 9 où vous faites = '.'. Join (ligne) au lieu de = ','. Join (ligne) c'est-à-dire un point dans les guillemets au lieu d'une virgule. Ou peut-être que les lignes dans chbs devraient être divisées sur des points au lieu de virgules plus tard. À l'heure actuelle, s'il y a trois lignes pour device7 dans chbs mais pas chst, le script vous le dira trois fois, mais votre description du problème implique que vous n'avez pas besoin de savoir combien de fois il apparaît. Voulez-vous vraiment cela ou un seul rapport est-il OK pour plusieurs occurrences? Dans ce cas, vous pouvez le simplifier en utilisant simplement le nom du périphérique comme clé de dictionnaire et en vérifiant si l'autre dictionnaire possède cette clé.

En ce moment, vous enregistrez les numéros de ligne, mais vous ne les utilisez pas vraiment. Si vous avez besoin de savoir combien de fois un périphérique apparaît, pourquoi ne pas le signaler au lieu de devoir les compter? Dans ce cas, lorsque vous ajoutez une clé de périphérique au dictionnaire, vérifiez d'abord si elle est déjà présente et si oui, incrémentez un compteur (peut-être dans un autre dictionnaire également associé au nom du périphérique).

+0

Merci Simon, en effet une faute de frappe. La façon dont je l'ai eu a pris trop de temps de toute façon si reconnaissant pour la réponse ci-dessus – Bill

Questions connexes