staging.inyokaproject.org

[PYTHON3] - 2 Textdateien vergleichen

Status: Ungelöst | Ubuntu-Version: Ubuntu 16.04 (Xenial Xerus)
Antworten |

halloICKEbins

Avatar von halloICKEbins

Anmeldungsdatum:
12. September 2017

Beiträge: 226

Morgen,

habe schon diverse Codesnipsel getestet (siehe nachfolgenden Quellcode) aber mir fehlt die Ausgabe von neuen Zeilen sowie das richtige Ausgeben von Änderungen, da ja wie im unteren Beispiel die Zeilen nicht direkt miteinander verglichen werden können.

Ziel ist es nachher running-configs zu vergleichen!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
with open(filename1) as f1:
   with open(filename2) as f2:
      file1list = f1.read().splitlines()
      file2list = f2.read().splitlines()
      list1length = len(file1list)
      list2length = len(file2list)
      if list1length == list2length:
          for index in range(len(file1list)):
              if file1list[index] == file2list[index]:
                  print (file1list[index] + "==" + file2list[index])
              else:                  
                  print (file1list[index] + "!=" + file2list[index]+" Not-Equel")
      else:
          print ("difference in the size of the file and number of lines")

Dazu nachfolgendes Beispiel:

filename1

Text1
Text2
Text3
Text4
Text5
Text6

filename2

Text1
Text2
Text2_neu1
Text2_neu2
Text3_neu3
Text3
Text4
Text4_neu1
Text5
Text6_geändert

Mein gewünschtes Ergebnis:

gleich
gleich
neue Zeile dazugekommen: Text2_neu1
neue Zeile dazugekommen: Text2_neu2
neue Zeile dazugekommen: Text2_neu3
gleich
gleich
neue Zeile dazugekommen: Text4_neu1
gleich
ungleich: alt - Text6; neu - Text6_geändert

Ist das überhaupt möglich, da ich dem Algorithmus ja beibringen muss was ein neuer Beitrag ist und welcher Eintrag eine Änderung darstellt???

Axel-Erfurt

Anmeldungsdatum:
18. Mai 2016

Beiträge: 1347

Schau dir mal simpleDiff an.

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

Spontan würde ich da einfach ein unified diff verwenden - das verzichtet darauf gleiche Zeilen darzustellen, wenn es nicht für den Kontext erforderlich ist (und sagt dir stattdessen, um welche Zeilen es geht) - das geht bequem mit der Standard Library:

1
2
3
4
5
6
7
8
9
import difflib
import sys

filename1, filename2 = "filename1", "filename2"

with open(filename1) as f1, open(filename2) as f2:
    sys.stdout.writelines(difflib.unified_diff(
        f1.readlines(), f2.readlines(),
        fromfile=filename1, tofile=filename2))

Für die Beispieldateien sieht das Ergebnis dann so aus:

$ python unified_diff.py 
--- filename1
+++ filename2
@@ -1,6 +1,10 @@
 Text1
 Text2
+Text2_neu1
+Text2_neu2
+Text3_neu3
 Text3
 Text4
+Text4_neu1
 Text5
-Text6
+Text6_geändert 

Wenn es eine Zeile mit einem führenden - vor einer mit einem führenden + gibt, weißt du, dass die Zeile geändert wurde, ansonsten wurde sie neu eingefügt.

Wenn du immer alle Zeilen sehen willst, kannst du difflib.Differ() nehmen:

1
2
3
4
5
6
7
8
import difflib
import sys

filename1, filename2 = "filename1.txt", "filename2.txt"

with open(filename1) as f1, open(filename2) as f2:
    sys.stdout.writelines(difflib.Differ().compare(
        f1.readlines(), f2.readlines()))
$ python differ.py 
  Text1
  Text2
+ Text2_neu1
+ Text2_neu2
+ Text3_neu3
  Text3
  Text4
+ Text4_neu1
  Text5
- Text6
+ Text6_geändert 

halloICKEbins

(Themenstarter)
Avatar von halloICKEbins

Anmeldungsdatum:
12. September 2017

Beiträge: 226

Schon mal Danke für die Hilfe.

Wie kann ich jetzt die Ausgabe so wie im nachfolgenden Beispiel formatieren (Zeilennr filename1/2 soll die Zeile des neuen bzw. alten Eintrages sein).

filename2 (neu):Zeilennr filename2: Text2_neu1
-----------------------------------------------------
filename2 (neu):Zeilennr filename2: Text2_neu2
-----------------------------------------------------
filename2 (neu):Zeilennr filename2: Text3_neu3
-----------------------------------------------------
filename2 (neu):Zeilennr filename2: Text4_neu1
-----------------------------------------------------
filename1 (alt):Zeilennr filename1: Text6
-----------------------------------------------------
filename2 (neu):Zeilennr filename2: Text6_geändert 

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

Mit dem gewünschten Ausgabeformat bekommt man eine ziemlich unübersichtliche Textwüste:

 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
import difflib
import sys

filename1, filename2 = "filename1.txt", "filename2.txt"

differ = difflib.Differ()
msg_template = "{} ({}):{}:"

with open(filename1) as f1, open(filename2) as f2:
    line_no_1 = 0
    line_no_2 = 0
    for line in differ.compare(
        f1.readlines(), f2.readlines()):
        if line.startswith('-'):
            line_no_2 -= 1
            line_no_1 += 1
            msg = msg_template.format(filename1, 'alt', line_no_1)
        elif line.startswith('+'):
            line_no_2 += 1
            msg = msg_template.format(filename2, 'neu', line_no_2)
        else:
            line_no_1 += 1
            line_no_2 += 1
            continue
        print(msg, line[2:], end='')
        print(54 * '-')
$ python compare2.py 
filename2.txt (neu):3: Text2_neu1
------------------------------------------------------
filename2.txt (neu):4: Text2_neu2
------------------------------------------------------
filename2.txt (neu):5: Text3_neu3
------------------------------------------------------
filename2.txt (neu):8: Text4_neu1
------------------------------------------------------
filename1.txt (alt):6: Text6
------------------------------------------------------
filename2.txt (neu):9: Text6_geändert
------------------------------------------------------ 

Wenn es für Menschen lesbar sein soll, würde ich einfach ein Tool wie meld, vimdiff, ediff für Emacs oder eines der anderen in Textdateien vergleichen genannten Helferlein nehmen, um zwei Dateien zu vergleichen.

halloICKEbins

(Themenstarter)
Avatar von halloICKEbins

Anmeldungsdatum:
12. September 2017

Beiträge: 226

@seahawk...hat mir sehr geholfen...ich habe es noch weiter in HTML gewandelt und Farbe benutzt - dann wird's übersichtlicher 😉

halloICKEbins

(Themenstarter)
Avatar von halloICKEbins

Anmeldungsdatum:
12. September 2017

Beiträge: 226

Mahlzeit,

habe bei meinem Script das nachfolgende Problem, dass er ^ - Zeichen setzt (sowie den zusätzlichen +/-, welcher da nicht hingehört) und ich nicht weiß, wo sie herkommen. In den Orginaldateien sind sie nicht vorhanden.

f_single

- !Time: Thu Jul 26 12:18:40 2018
- ^ 
+ !Time: Thu Jul 26 12:21:50 2018
+ ^ 

f_all

- !Time: Thu Jul 26 12:18:40 2018
+ !Time: Thu Jul 26 12:21:50 2018

In der 'f_single' sind die ^ - Zeichen und in der 'f_all' nicht! Warum?

 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
import difflib
import sys
import os

def compare_configfiles(last_configfile, new_configfile, single_comparision_file, all_comparision_file):
    
    counter = 0
    
    f_single = open(single_comparision_file, 'w')
    f_all = open(all_comparision_file, 'a')
    
    differ = difflib.Differ()
    
    with open(last_configfile) as f1, open(new_configfile) as f2:
        line_no_1 = 0
        line_no_2 = 0
        for line in differ.compare(f1.readlines(), f2.readlines()):
            line = line.split('\n')[0]
            if line.startswith('-'):
                counter += 1
                line_no_2 -= 1
                line_no_1 += 1
                print ('- |||' + str(line[2:]) + '|||' + ' (' + str(os.path.basename(last_configfile)) + ' - Zeile: ' + str(line_no_1) + ')', file=f_single)
                print ('- |||' + str(line[2:]) + '|||' + ' (' + str(os.path.basename(last_configfile)) + ' - Zeile: ' + str(line_no_1) + ')', file=f_all)
            elif line.startswith('+'):
                counter += 1
                line_no_2 += 1
                print ('+ |||' + str(line[2:]) + '|||' + ' (' + str(os.path.basename(new_configfile)) + ' - Zeile: ' + str(line_no_2) + ')', file=f_single)
                print ('+ |||' + str(line[2:]) + '|||' + ' (' + str(os.path.basename(new_configfile)) + ' - Zeile: ' + str(line_no_1) + ')', file=f_all)
            else:
                line_no_1 += 1
                line_no_2 += 1
                print (str(line[2:]), file=f_single)
    
    f.close()

halloICKEbins

(Themenstarter)
Avatar von halloICKEbins

Anmeldungsdatum:
12. September 2017

Beiträge: 226

Habe noch ein anderes Problem...

- !Time: Thu Jul 26 12:18:40 2018
+ !Time: Thu Jul 26 12:21:50 2018
...

Bei den Zeilen handelt es sich im eigentlichen Sinne nicht um eine wirkliche Änderung, da der Rest der config in diesem Fall gleich bleibt und nur die Zeit eine Andere ist. Wie kann ich ich jetzt sinnvoll zum Beispiel nach '!Time:' filtern, damit er dies nicht als Anderung vermerkt? Also entweder garnicht erst wegschreiben in die Dateien bzw. im Vorfeld rausfiltern.

Noch komplizierter finde ich es im nachfolgenden Beispiel, wo sich nur die Holdtime von 158 zu 176 ändert - also auch keine wirkliche Änderung!

- Eth1/1 158 R S I s BBB-BBBBBB-1 Eth1/1
+ Eth1/1 176 R S I s BBB-BBBBBB-1 Eth1/1
...

noisefloor Team-Icon

Anmeldungsdatum:
6. Juni 2006

Beiträge: 29567

Hallo,

das ^ zeigt an, wo sich was geändert hat - siehe auch Beispiele in der Python-Doku zu difflib.

also auch keine wirkliche Änderung!

Natürlich ist es eine Änderung. Computer sind grundsätzlich "dumm" und vergleichen Zeile für Zeile, Zeichen für Zeichen, ... Nur weil es für _dich_ keine Änderung ist, weil du den Text direkt beim Lesen "interpretierst", ist es für den Computer trotzdem eine. Wenn du so viel "Intelligenz" vom Computer erwartest, kommst du in der Regel mit so einfachen Tools wie difflib & Co nicht mehr aus.

Gruß, noisefloor

halloICKEbins

(Themenstarter)
Avatar von halloICKEbins

Anmeldungsdatum:
12. September 2017

Beiträge: 226

Aber warum macht er es bei der einen Datei und bei der anderen nicht?

noisefloor Team-Icon

Anmeldungsdatum:
6. Juni 2006

Beiträge: 29567

Hallo,

da müsstest du mal deine _original_ Dateien hier posten, damit wir selber damit "herumspielen" können. So remote können wir ja nicht raten / sehen, was in den Dateien drin ist, welche nicht-druckbaren Zeichen vielleicht drin sind etc.

Gruß, noisefloor

halloICKEbins

(Themenstarter)
Avatar von halloICKEbins

Anmeldungsdatum:
12. September 2017

Beiträge: 226

Ich schaff's leider vorm Urlaub nicht mehr ... melde mich "viel später" nochmal!

Antworten |