Использование 'diff' (или чего-либо еще) для получения различий на уровне символов между текстовыми файлами - PullRequest
72 голосов
/ 12 ноября 2009

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

Вы меня поняли.

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

Ответы [ 14 ]

53 голосов
/ 11 июля 2015

В 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 http://oi60.tinypic.com/160wpb4.jpg

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

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

19 голосов
/ 05 октября 2016

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

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.

16 голосов
/ 23 декабря 2009

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

cmp

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

15 голосов
/ 12 ноября 2009

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

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

7 голосов
/ 26 декабря 2013

В 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)
5 голосов
/ 01 декабря 2016

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

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

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

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

5 голосов
/ 21 ноября 2013
cmp -l file1 file2 | wc

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

4 голосов
/ 05 октября 2016

Цветной, уровень персонажа diff выход

Вот что вы можете сделать с помощью приведенного ниже сценария и diff-highlight (который является частью git):

Coloured diff screenshot

#!/bin/sh -eu

# Use diff-highlight to show word-level differences

diff -U3 --minimal "$@" |
  sed 's/^-/\x1b[1;31m-/;s/^+/\x1b[1;32m+/;s/^@/\x1b[1;34m@/;s/$/\x1b[0m/' |
  diff-highlight

(Кредит @ ответ retracile для выделения sed)

3 голосов
/ 23 июля 2014

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

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

3 голосов
/ 12 ноября 2009

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

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

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

...