Разница в пробелах между двумя файлами в Linux


15

У меня есть два файла, которые при сравнении с diff показывают, что каждая строка изменилась. Когда я сравниваю их с diff -w(игнорируя пробелы), это показывает несколько минимальных изменений, которые я ожидаю.

Очевидно, между пробелами в каждом файле есть некоторая разница, но я не знаю, что это такое и как их найти. Я попытался отредактировать файлы, чтобы убедиться, что пробел на самом деле является пробелом (в отличие от вкладок), но я не уверен, что еще делать.

Я использовал vim с, :set list onчтобы подтвердить, что в конце строк нет пробела.

Я также считаю, что в каждом файле есть разделители строк в Linux, поскольку vim не показывал их ^Mв конце строк.


1
Вы проверили на наличие пробела (в конце строки)? Такое пространство будет обнаружено, diffно многие редакторы по умолчанию в любом случае не делают это пространство видимым.
John1024

Хорошее предложение. Я использовал vim с ": set list on", это показывало "$" в конце строки, а пробела не было. Я
обновлю

Если вы vimпользователь, то пытались ли вы использовать, vimdiff file1 file2чтобы увидеть, в чем различия?
John1024

@ John1024 Я не знал о vimdiff, но это выглядит многообещающе. Добавьте это как ответ, и я приму
Ромски

1
Vim показывает ^ M только тогда, когда он неправильно определяет окончание строки Unix, но файл на самом деле имеет конец строки DOS. Обычно это происходит, если у вас смешанная строка, оканчивающаяся на один файл, например, применение патча с концом строки, отличным от исходного файла. Когда vim обнаружит, что строка DOS заканчивается правильно, она не показала бы ^ M.
Ли Райан

Ответы:


7

Для vimпользователей есть удобная утилита, показывающая точные различия между файлами:

vimdiff file1 file2

Это поместит каждый файл в окна, бок о бок, и различия будут выделены цветом.

Некоторые полезные команды, когда в vimdiff

В то время как в vimdiff, некоторые полезные команды:

  • ]c: перейти к следующему изменению

  • [c: перейти к предыдущему изменению

  • ctrl-W ctrl-W: переключиться в другое окно

  • zo: открытые складки

  • zc: закрыть складки

пример

Вот пример vimdiffв xtermсравнения двух версий cupsфайла конфигурации:

введите описание изображения здесь

Вы можете видеть, что длинные участки одинаковых линий были свернуты. Их можно открыть снова с помощью zo.

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


14

В FreeBSD или в большинстве систем Linux вы можете передать вывод diff, cat -v -e -tчтобы показать различия между пробелами.

diff file1 file2 | cat -vet

Вкладки будут отображаться как ^I, а $будет отображаться в конце каждой строки, так что вы можете увидеть конечный пробел, а непечатаемые символы будут отображаться как ^Xили M-X.

Если у вас есть GNU coreutils (доступно в большинстве не занятых дистрибутивов Linux), это можно упростить до

diff file1 file2 | cat -A

В системах busybox используйте catv -vet.


2

Был ли один из файлов отредактирован на компьютере с Windows?

Стандартное завершение строки в Windows - это CRLF, где в Linux это просто LF (а в Mac это был CR, но я подозреваю, что это изменилось со времен OS X).

Попробуйте wc -lфайлы и посмотрите, сколько строк, а затем посмотрите, не отличается ли разница в размере от количества строк (последняя строка может не заканчиваться в одном файле).


Спасибо за быстрый ответ. Подсчет строк показывает, что в одном файле есть еще 5 строк (я ожидаю, что я внес изменения). Я получил один файл с Linux-машины, а другой был извлечен из репозитория кода на Linux. Я считаю, что при просмотре файла с терминаторами Windows в vim последний символ будет отображаться как ^ M, но это не так.
Ромски

3
vim на самом деле достаточно умен, чтобы автоматически определять завершение строки, подробности смотрите в stackoverflow.com/questions/3852868 .
фехтовальный столб

Я не знал об этом! Я перепроверю
Ромски

2

odможет помочь Команда Octal Dump может показывать содержимое в шестнадцатеричном формате. Это может помочь вам увидеть, какие байты, включая нулевые байты или неожиданный пробел, находятся в файле. Возможными общими причинами могут быть LF против CRLF, табуляции против пробелов или ASCII против юникода (у которых часто может быть нулевой байт перед каждым обычно видимым байтом). od -x filenameдолжен раскрыть любой из этих шаблонов. Если вы хотите более сложный способ просмотра файла, подойдет любой «шестнадцатеричный редактор». Приятно то, odчто, как и cutкоманда, она встроена во многие системы Unix. Поэтому зачастую не требуется отдельная установка.

Если вам нужно, чтобы файлы были более похожими, trможете внести некоторые изменения и sedсделать больше. Вероятно, я бы начал с того, ls -lчтобы увидеть, какой файл больше, затем просмотрите байты, чтобы увидеть, что нужно изменить, а затем измените один из файлов, чтобы они казались более похожими.


1

Чтобы узнать, где настоящие пробелы и вкладки, вы можете заменить их, sedнапример:

$ cat file
  line 1
  line 2
    line 6
        line 7
$ sed 's/ /-/g; s/\t/<tab>/g' file
--line-1
--line-2
<tab>line-6
<tab><tab>line-7

А теперь сравните два файла.


Еще лучше, вы можете запустить этот фильтр на выходе diff. Или вы можете использовать готовый фильтр cat, как в superuser.com/a/913368/37154
clacke

0

Следующее содержание было скопировано здесь из раздела «вопрос» выше, который был написан Ромски.

Оба vimdiffи diff file1 file2 | cat -Aбыли очень полезны с точки зрения инструментов.

Наконец, я нашел еще одну проблему. Некоторые из моих файлов были закодированы с помощью UTF-8 BOM. Это было выделено с помощью diff file1 file2 | cat -A. Это проявилось как M-oM-;M-?в начале затронутого файла:

$ diff file1 file2 | cat -A
< package com.mycompany;$
---$
> M-oM-;M-?package com.mycompany;$

Несмотря на ряд проблем, я перечислил несколько команд ниже для тех, кто нуждается в очистке своих файлов:

# recursively remove UTF8 BOM
find . -type f -exec sed -i -e '1s/^\xEF\xBB\xBF//' {} \;

# recursively replace CRLF with LF
find . -type f -print0 | xargs -0 dos2unix
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.