Сравнение двух различий отчетов в python
У меня есть 2 файла под названием "hosts" (в разных каталогах)
Я хочу сравнить их с помощью python, чтобы узнать, являются ли они ИДЕНТИЧНЫМИ. Если они не идентичны, я хочу напечатать разницу на экране.
До сих пор я пробовал это
hosts0 = open(dst1 + "/hosts","r")
hosts1 = open(dst2 + "/hosts","r")
lines1 = hosts0.readlines()
for i,lines2 in enumerate(hosts1):
if lines2 != lines1[i]:
print "line ", i, " in hosts1 is different \n"
print lines2
else:
print "same"
Но когда я запускаю это, я получаю
File "./audit.py", line 34, in <module>
if lines2 != lines1[i]:
IndexError: list index out of range
Это означает, что один из хостов имеет больше строк, чем другой.
Есть ли лучший способ сравнить 2 файла и сообщить о различии?
Ответы
Ответ 1
import difflib
lines1 = '''
dog
cat
bird
buffalo
gophers
hound
horse
'''.strip().splitlines()
lines2 = '''
cat
dog
bird
buffalo
gopher
horse
mouse
'''.strip().splitlines()
# Changes:
# swapped positions of cat and dog
# changed gophers to gopher
# removed hound
# added mouse
for line in difflib.unified_diff(lines1, lines2, fromfile='file1', tofile='file2', lineterm=''):
print line
Выводит следующее:
--- file1
+++ file2
@@ -1,7 +1,7 @@
+cat
dog
-cat
bird
buffalo
-gophers
-hound
+gopher
horse
+mouse
Этот diff дает вам контекстные линии, чтобы помочь понять, как этот файл отличается. Вы можете увидеть "кошку" здесь дважды, потому что она была удалена снизу "собака" и добавлена над ней.
Вы можете использовать n = 0 для удаления контекста.
for line in difflib.unified_diff(lines1, lines2, fromfile='file1', tofile='file2', lineterm='', n=0):
print line
Вывод:
--- file1
+++ file2
@@ -0,0 +1 @@
+cat
@@ -2 +2,0 @@
-cat
@@ -5,2 +5 @@
-gophers
-hound
+gopher
@@ -7,0 +7 @@
+mouse
Но теперь он заполнен строками "@@", в которых вам указана позиция в файле, который изменился. Позвольте удалить дополнительные строки, чтобы сделать его более читаемым.
for line in difflib.unified_diff(lines1, lines2, fromfile='file1', tofile='file2', lineterm='', n=0):
for prefix in ('---', '+++', '@@'):
if line.startswith(prefix):
break
else:
print line
Предоставление нам этого результата:
+cat
-cat
-gophers
-hound
+gopher
+mouse
Теперь, что вы хотите сделать?
Если вы проигнорируете все удаленные строки, вы не увидите, что "собака" была удалена.
Если вы счастливы, просто показывая дополнения к файлу, вы можете сделать это:
diff = difflib.unified_diff(lines1, lines2, fromfile='file1', tofile='file2', lineterm='', n=0)
lines = list(diff)[2:]
added = [line[1:] for line in lines if line[0] == '+']
removed = [line[1:] for line in lines if line[0] == '-']
print 'additions:'
for line in added:
print line
print
print 'additions, ignoring position'
for line in added:
if line not in removed:
print line
Выведение:
additions:
cat
gopher
mouse
additions, ignoring position:
gopher
mouse
Вероятно, вы уже можете сказать, что существуют различные способы "распечатать различия" двух файлов, поэтому вам нужно будет быть очень конкретным, если вам нужна дополнительная помощь.
Ответ 2
Библиотека difflib полезна для этого и входит в стандартную библиотеку. Мне нравится унифицированный формат diff.
http://docs.python.org/2/library/difflib.html#difflib.unified_diff
import difflib
import sys
with open('/tmp/hosts0', 'r') as hosts0:
with open('/tmp/hosts1', 'r') as hosts1:
diff = difflib.unified_diff(
hosts0.readlines(),
hosts1.readlines(),
fromfile='hosts0',
tofile='hosts1',
)
for line in diff:
sys.stdout.write(line)
Выходы:
--- hosts0
+++ hosts1
@@ -1,5 +1,4 @@
one
two
-dogs
three
И вот хитрая версия, которая игнорирует определенные строки.
Там могут быть краевые случаи, которые не работают, и, безусловно, есть лучшие способы сделать это, но, возможно, это будет достаточно для ваших целей.
import difflib
import sys
with open('/tmp/hosts0', 'r') as hosts0:
with open('/tmp/hosts1', 'r') as hosts1:
diff = difflib.unified_diff(
hosts0.readlines(),
hosts1.readlines(),
fromfile='hosts0',
tofile='hosts1',
n=0,
)
for line in diff:
for prefix in ('---', '+++', '@@'):
if line.startswith(prefix):
break
else:
sys.stdout.write(line[1:])
Ответ 3
hosts0 = open("C:path\\a.txt","r")
hosts1 = open("C:path\\b.txt","r")
lines1 = hosts0.readlines()
for i,lines2 in enumerate(hosts1):
if lines2 != lines1[i]:
print "line ", i, " in hosts1 is different \n"
print lines2
else:
print "same"
Приведенный выше код работает для меня. Можете ли вы указать, с какой ошибкой вы сталкиваетесь?
Ответ 4
Вы можете добавить условный оператор. Если ваш массив выходит за пределы индекса, то перерыв и печать остальной части файла.
Ответ 5
import difflib
f=open('a.txt','r') #open a file
f1=open('b.txt','r') #open another file to compare
str1=f.read()
str2=f1.read()
str1=str1.split() #split the words in file by default through the spce
str2=str2.split()
d=difflib.Differ() # compare and just print
diff=list(d.compare(str2,str1))
print '\n'.join(diff)