Ответ 1
Я не проверял библиотеку python, но в итоге нашел решение Google, достаточно хорошее для того, что мне было нужно. И он реализован на многих языках (среди них С#). Я был впечатлен.
Я хотел бы использовать "diff", чтобы получить как разницу между линией, так и разницу символов. Например, рассмотрим:
Файл 1
abcde
abc
abcccd
Файл 2
abcde
ab
abccc
Используя diff -u, я получаю:
@@ -1,3 +1,3 @@
abcde
-abc
-abcccd
\ No newline at end of file
+ab
+abccc
\ No newline at end of file
Однако это только показывает мне, что были изменения в этих строках. Я бы хотел увидеть что-то вроде:
@@ -1,3 +1,3 @@
abcde
-ab<ins>c</ins>
-abccc<ins>d</ins>
\ No newline at end of file
+ab
+abccc
\ No newline at end of file
Вы получите мой дрейф.
Теперь я знаю, что могу использовать другие двигатели, чтобы отметить/проверить разницу на определенной строке. Но я бы предпочел использовать один инструмент, который сделает все это.
Я не проверял библиотеку python, но в итоге нашел решение Google, достаточно хорошее для того, что мне было нужно. И он реализован на многих языках (среди них С#). Я был впечатлен.
В Git есть слово diff, и определение всех символов как слов эффективно дает вам различие символов. Тем не менее, изменения новой строки игнорируются.
Пример:
Создайте репозиторий следующим образом:
mkdir chardifftest
cd chardifftest
git init
echo -e 'foobarbaz\ncatdog\nfox' > file
git add -A; git commit -m 1
echo -e 'fuobArbas\ncat\ndogfox' > file
git add -A; git commit -m 2
Теперь сделайте git diff --word-diff=color --word-diff-regex=. master^ master
, и вы получите:
Обратите внимание, что как добавления, так и удаления распознаются на уровне символов, а добавления и удаления новых строк игнорируются.
Вы также можете попробовать
git diff --word-diff=plain --word-diff-regex=. master^ master
и
git diff --word-diff=porcelain --word-diff-regex=. master^ master
Вы можете использовать:
diff -u f1 f2 |colordiff |diff-highlight
colordiff
- это пакет Ubuntu. Вы можете установить его, используя sudo apt-get install colordiff
.
diff-highlight
из git (начиная с версии 2.9). Он находится в /usr/share/doc/git/contrib/diff-highlight/diff-highlight
. Вы можете поместить это где-нибудь в свой $PATH
.
Python difflib - это туз, если вы хотите сделать это программно. Для интерактивного использования я использую vim diff mode (достаточно просто использовать: просто вызовите vim с vimdiff a b
). Я также иногда использую Beyond Compare, который делает почти все, на что вы могли бы надеяться, из инструмента diff.
Я не вижу никакого инструмента командной строки, который делает это с пользой, но, как отмечает Уилл, код примера difflib может помочь.
Вы можете использовать команду cmp
в Solaris:
cmp
Сравните два файла и, если они отличаются, сообщает первый байт и номер строки, где они отличаются.
У Python есть удобная библиотека с именем difflib
, которая может помочь ответить на ваш вопрос.
Ниже приведены два oneliners, использующих difflib
для разных версий python.
python3 -c 'import difflib, sys; \
print("".join( \
difflib.ndiff( \
open(sys.argv[1]).readlines(),open(sys.argv[2]).readlines())))'
python2 -c 'import difflib, sys; \
print "".join( \
difflib.ndiff( \
open(sys.argv[1]).readlines(), open(sys.argv[2]).readlines()))'
Они могут пригодиться как псевдоним оболочки, который легче перемещать с помощью .${SHELL_NAME}rc
.
$ alias char_diff="python2 -c 'import difflib, sys; print \"\".join(difflib.ndiff(open(sys.argv[1]).readlines(), open(sys.argv[2]).readlines()))'"
$ char_diff old_file new_file
И более читаемая версия для размещения автономного файла.
#!/usr/bin/env python2
from __future__ import with_statement
import difflib
import sys
with open(sys.argv[1]) as old_f, open(sys.argv[2]) as new_f:
old_lines, new_lines = old_f.readlines(), new_f.readlines()
diff = difflib.ndiff(old_lines, new_lines)
print ''.join(diff)
cmp -l file1 file2 | wc
Хорошо работал у меня. Самый левый номер результата указывает количество символов, которые отличаются.
Я также написал свой собственный сценарий для решения этой проблемы, используя алгоритм самой длинной общей подпоследовательности.
Выполнено как таковое
JLDiff.py a.txt b.txt out.html
Результат в HTML с красной и зеленой окраской. Для больших файлов экспоненциально требуется больше времени для обработки, но это делает истинное посимвольное сравнение без проверки построчно.
Цветной, на уровне символа diff
выход
Вот что вы можете сделать с приведенными ниже script и diff-highlight (который является частью git):
#!/bin/sh -eu
# Use diff-highlight to show word-level differences
diff -U3 --minimal "[email protected]" |
sed 's/^-/\x1b[1;31m-/;s/^+/\x1b[1;32m+/;s/^@/\x1b[1;[email protected]/;s/$/\x1b[0m/' |
diff-highlight
(кредит @retracile answer для выделения sed
)
Python difflib может это сделать.
Документация включает в себя пример программа командной строки для вас.
Точный формат не такой, как вы указали, но было бы просто проанализировать выход ndiff-стиля или изменить примерную программу для генерации ваших обозначений.
Вот интерактивный инструмент сравнения текста: http://text-compare.com/
Он может выделить каждый отдельный char, который отличается и продолжает сравнивать остальные.
Я думаю, что более простое решение всегда является хорошим решением. В моем случае код ниже помогает мне. Я надеюсь, что это помогает кто-либо другой.
#!/bin/env python
def readfile( fileName ):
f = open( fileName )
c = f.read()
f.close()
return c
def diff( s1, s2 ):
counter=0
for ch1, ch2 in zip( s1, s2 ):
if not ch1 == ch2:
break
counter+=1
return counter < len( s1 ) and counter or -1
import sys
f1 = readfile( sys.argv[1] )
f2 = readfile( sys.argv[2] )
pos = diff( f1, f2 )
end = pos+200
if pos >= 0:
print "Different at:", pos
print ">", f1[pos:end]
print "<", f2[pos:end]
Вы можете сравнить два файла со следующим синтаксисом на вашем любимом терминале:
$ ./diff.py fileNumber1 fileNumber2
Если вы сохраняете свои файлы в Git, вы можете различать версии с diff-highlight script, который будет показывать разные линии с выделенными различиями.
К сожалению, он работает только тогда, когда количество удаленных строк совпадает с количеством добавленных строк - существует код-заглушка, когда строки не совпадают, поэтому предположительно это может быть исправлено в будущем.
Не полный ответ, но если вывод cmp -l
недостаточно ясен, вы можете использовать:
sed 's/\(.\)/\1\n/g' file1 > file1.vertical
sed 's/\(.\)/\1\n/g' file2 > file2.vertical
diff file1.vertical file2.vertical
В большинстве этих ответов упоминается использование diff-highlight, модуля Perl. Но я не хотел выяснять, как установить модуль Perl. Поэтому я сделал несколько небольших изменений, чтобы он стал автономным скриптом Perl.
Вы можете установить его используя:
▶ curl -o /usr/local/bin/DiffHighlight.pl \
https://raw.githubusercontent.com/alexharv074/scripts/master/DiffHighlight.pl
И использование (если у вас есть Ubuntu colordiff
упомянутый в ответе zhanxw):
▶ diff -u f1 f2 | colordiff | DiffHighlight.pl
И использование (если вы этого не сделаете):
▶ diff -u f1 f2 | DiffHighlight.pl