Подтвердить что ты не робот

Используя "diff" (или что-то еще), чтобы получить разницу между текстовыми файлами на уровне символов

Я хотел бы использовать "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

Вы получите мой дрейф.

Теперь я знаю, что могу использовать другие двигатели, чтобы отметить/проверить разницу на определенной строке. Но я бы предпочел использовать один инструмент, который сделает все это.

4b9b3361

Ответ 1

Я не проверял библиотеку python, но в итоге нашел решение Google, достаточно хорошее для того, что мне было нужно. И он реализован на многих языках (среди них С#). Я был впечатлен.

Ответ 2

В 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

Обратите внимание, что как добавления, так и удаления распознаются на уровне символов, а добавления и удаления новых строк игнорируются.

Вы также можете попробовать
git diff --word-diff=plain --word-diff-regex=. master^ master
и
git diff --word-diff=porcelain --word-diff-regex=. master^ master

Ответ 3

Вы можете использовать:

diff -u f1 f2 |colordiff |diff-highlight

screenshot

colordiff - это пакет Ubuntu. Вы можете установить его, используя sudo apt-get install colordiff.

diff-highlight из git (начиная с версии 2.9). Он находится в /usr/share/doc/git/contrib/diff-highlight/diff-highlight. Вы можете поместить это где-нибудь в свой $PATH.

Ответ 4

Python difflib - это туз, если вы хотите сделать это программно. Для интерактивного использования я использую vim diff mode (достаточно просто использовать: просто вызовите vim с vimdiff a b). Я также иногда использую Beyond Compare, который делает почти все, на что вы могли бы надеяться, из инструмента diff.

Я не вижу никакого инструмента командной строки, который делает это с пользой, но, как отмечает Уилл, код примера difflib может помочь.

Ответ 5

Вы можете использовать команду cmp в Solaris:

cmp

Сравните два файла и, если они отличаются, сообщает первый байт и номер строки, где они отличаются.

Ответ 6

У 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)

Ответ 7

cmp -l file1 file2 | wc

Хорошо работал у меня. Самый левый номер результата указывает количество символов, которые отличаются.

Ответ 8

Я также написал свой собственный сценарий для решения этой проблемы, используя алгоритм самой длинной общей подпоследовательности.

Выполнено как таковое

JLDiff.py a.txt b.txt out.html

Результат в HTML с красной и зеленой окраской. Для больших файлов экспоненциально требуется больше времени для обработки, но это делает истинное посимвольное сравнение без проверки построчно.

Ответ 9

Цветной, на уровне символа 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)

Ответ 10

Python difflib может это сделать.

Документация включает в себя пример программа командной строки для вас.

Точный формат не такой, как вы указали, но было бы просто проанализировать выход ndiff-стиля или изменить примерную программу для генерации ваших обозначений.

Ответ 11

Вот интерактивный инструмент сравнения текста: http://text-compare.com/

Он может выделить каждый отдельный char, который отличается и продолжает сравнивать остальные.

Ответ 12

Я думаю, что более простое решение всегда является хорошим решением. В моем случае код ниже помогает мне. Я надеюсь, что это помогает кто-либо другой.

#!/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

Ответ 13

Если вы сохраняете свои файлы в Git, вы можете различать версии с diff-highlight script, который будет показывать разные линии с выделенными различиями.

К сожалению, он работает только тогда, когда количество удаленных строк совпадает с количеством добавленных строк - существует код-заглушка, когда строки не совпадают, поэтому предположительно это может быть исправлено в будущем.

Ответ 14

Не полный ответ, но если вывод cmp -l недостаточно ясен, вы можете использовать:

sed 's/\(.\)/\1\n/g' file1 > file1.vertical
sed 's/\(.\)/\1\n/g' file2 > file2.vertical
diff file1.vertical file2.vertical

Ответ 15

В большинстве этих ответов упоминается использование 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