Я пробовал diff, но он генерирует некоторые числа и другие символы перед разными строками, что затрудняет сравнение файлов.
Вс,
Ответы:
216
diff (1) - это не ответ, но comm (1) - это ответ.
NAME
comm - compare two sorted files line by line
SYNOPSIS
comm [OPTION]... FILE1 FILE2
...-1 suppress lines unique to FILE1
-2 suppress lines unique to FILE2
-3 suppress lines that appear in both files
Так
comm -2-3 file1 file2 > file3
Входные файлы необходимо отсортировать. Если это не так, сначала отсортируйте их. Это можно сделать с помощью временного файла или ...
comm -2-3<(sort file1)<(sort file2)> file3
при условии, что ваша оболочка поддерживает подстановку процессов (bash поддерживает).
Помните, что два файла должны быть отсортированы и уникальны
Энди
6
Вы можете сгруппировать варианты вместе:comm -23
Paolo M
Что значит «отсортировано»? Что строки имеют одинаковый порядок? Тогда это, вероятно, нормально для большинства случаев использования - например, проверка того, какие строки были добавлены, путем сравнения с резервной более старой версией. Если вновь добавленные строки не могут находиться между существующими строками, это большая проблема.
Егор Ганс
@EgorHans: если в файле есть, например, строки, содержащие целые числа, такие как "3 \ n1 \ n3 \ n2 \ n", строки должны быть сначала переупорядочены в порядке возрастания или убывания, например, "\ 1 \ n2 \ n3 \ n3 \ n" с дубликатами. смежны. Это «отсортировано», и оба файла должны быть отсортированы аналогичным образом. Когда в новом файле есть новые строки, не имеет значения, находятся ли они «между существующими строками», потому что после сортировки их нет, они отсортированы.
sorpigal
48
Утилита Unix diffпредназначена именно для этой цели.
$ diff -u file1 file2 > file3
См. Руководство и Интернет для получения информации о вариантах, различных форматах вывода и т. Д.
Это не выполняет запрошенную работу; он вставляет кучу дополнительных символов, даже с использованием переключателей командной строки, предложенных в других ответах.
xenocyon
20
Рассмотрим это:
файл a.txt:
abcd
efgh
файл b.txt:
abcd
Вы можете найти разницу с:
diff -a --suppress-common-lines -y a.txt b.txt
Результат будет:
efgh
Вы можете перенаправить вывод в выходной файл (c.txt), используя:
diff -a --suppress-common-lines -y a.txt b.txt > c.txt
Это ответит на ваш вопрос:
"... который содержит строки в файле1, которых нет в файле2."
У этого ответа два ограничения: (1) он работает только для коротких строк (по умолчанию менее 80 символов, хотя это можно изменить) и, что более важно, (2) он добавляет «<» в конце каждого строка, которую нужно удалить другой программой (например, awk, sed).
сергут
Во многих случаях вы также захотите использовать -d, что сделает diffвсе возможное, чтобы найти наименьшее возможное различие. -i, -E, -w, -BИ --suppress-blank-emptyтакже может быть полезно время от времени, хотя и не всегда. Если вы не знаете, что подходит вашему варианту использования, попробуйте diff --helpсначала (что обычно является хорошей идеей, если вы не знаете, что может делать команда).
Егор Ганс
Кроме того, используя --line-format =% L, вы удерживаете diff от генерации каких-либо дополнительных символов (по крайней мере, в справке сказано, что это работает так, но мы собираемся попробовать).
Иногда diffэто именно та утилита, которая вам нужна, но иногда joinболее подходящая. Файлы должны быть предварительно отсортированы или, если вы используете оболочку, которая поддерживает подстановку процессов, такую как bash, ksh или zsh, вы можете выполнять сортировку на лету.
join -v 1<(sort file1)<(sort file2)
Приостановлено до дальнейшего уведомления. источник
За это надо получить медаль! Это было именно то, что я искал последние 2 часа
Затарра
7
Пытаться
sdiff file1 file2
У меня это обычно работает намного лучше в большинстве случаев. Вы можете предварительно отсортировать файлы, если порядок строк не важен (например, некоторые текстовые файлы конфигурации).
Хорошая утилита! Мне нравится, как он отмечает отличительные линии. Делает сравнение конфигураций намного проще. Это вместе с sort - смертельная комбинация (например sdiff <(sort file1) <(sort file2))
jmagnusson
3
Если вам нужно решить эту проблему с помощью coreutils, принятый ответ хорош:
comm -23<(sort file1)<(sort file2)> file3
Вы также можете использовать sd (stream diff), который не требует сортировки или подстановки процессов и поддерживает бесконечные потоки, например:
cat file1 | sd 'cat file2'> file3
Возможно, не так много пользы в этом примере, но все же учтите это; в некоторых случаях вы не сможете использовать commни grep -Fни diff.
Вот пост в блоге, который я написал о различиях между потоками на терминале, который представляет sd.
Уже много ответов, но ИМХО ни один из них не идеален. Ответ Танатоса оставляет несколько дополнительных символов в строке, а ответ Сорпигала требует, чтобы файлы были отсортированы или предварительно отсортированы, что может быть неадекватным во всех обстоятельствах.
Я думаю , что лучший способ получения линий , которые не отличаются , и больше ничего (никаких дополнительных символов, без повторного заказа) представляет собой комбинацию diff, grepи awk(или аналогичный).
Если в строках нет символа «<», коротким однострочником может быть:
diff urls.txt*| grep "<"| sed 's/< //g'
но это удалит все экземпляры «<» (меньше, чем пробел) из строк, что не всегда нормально (например, исходный код). Самый безопасный вариант - использовать awk:
Этот однострочник сравнивает оба файла, затем отфильтровывает вывод diff в стиле ed, а затем удаляет завершающий "<", который добавляет diff. Это работает, даже если в самих строках есть «<».
comm не требует сортировки (в более новых версиях?) - просто используйте --nocheck-order. Я часто использую это при манипулировании csvs из интерфейса командной строки
ak5 06
2
Я удивлен, что никто не упомянул diff -yо параллельном выводе , например:
diff -y file1 file2 > file3
И в file3(разные строки имеют символ |посередине):
Я перепробовал почти все ответы в этой теме, но ни один из них не был полным. После нескольких трасс выше один работал у меня. diff даст вам разницу, но с некоторыми нежелательными специальными характеристиками. где ваши фактические разностные линии начинаются с '>'. так что следующий шаг - строки grep начинаются с '>', а затем удаляются с помощью sed .
Это плохая идея. Вам также потребуется изменить строки, начинающиеся с <. Вы увидите это, если поменяете порядок входных файлов. Даже если бы вы сделали это, вы бы предпочли опустить grep, используя больше sed: `diff a1 a2 | sed '/> / s ///' `Это может привести к разрыву строк, содержащих >или <в правильной ситуации, и по- прежнему оставлять лишние строки, описывающие номера строк. Если вы хотите попробовать этот подход лучше всего было бы: diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'.
sorpigal 06
0
Вы можете использовать diffследующее форматирование вывода:
--old-line-format='', отключите вывод для файла1, если строка отличается от сравнения в файле2. --unchanged-line-format='', отключите вывод, если строки совпадают.
Если у вас есть файл CSV с одним или даже несколькими столбцами , вы можете выполнять эти построчные операции «diff», используя встроенную базу данных sqlite3. Он поставляется с питоном, поэтому должен быть доступен на большинстве Linux / Mac. Вы можете создать сценарий команд sqlite3 в оболочке bash без необходимости писать python.
Создайте файлы a.csv и b.csv
Убедитесь, что sqlite3 установлен с помощью команды "sqlite3 -help"
Выполните приведенные ниже команды непосредственно в оболочке Linux / Mac (или поместите ее в сценарий)
echo "
.mode csv
.import a.csv atable
.import b.csv btable
create table result as select * from atable EXCEPT select * from btable;
.output result.csv
select * from result ;
.quit
"| sqlite3 temp.db
Примечание: Убедитесь , что существует новая строка для каждой из команд sqlite3.
Как это устроено
Импортируйте 2 CSV в таблицы «atable» и «btable» соответственно.
Используйте оператор sql " except ", чтобы выбрать данные, доступные в "atable", но отсутствующие в "btable". Создайте таблицу «результатов», используя оператор select query
Выведите таблицу результатов в result.csv, выполнив команду «select * from result;»
Если вам нужно работать с конкретными столбцами, вам подойдет sqlite3 или любой db.
Я пробовал различать несколько файлов GB, используя встроенные инструменты diff и comm. Sqlite на милю превосходит утилиты Linux.
Ответы:
diff (1) - это не ответ, но comm (1) - это ответ.
Так
Входные файлы необходимо отсортировать. Если это не так, сначала отсортируйте их. Это можно сделать с помощью временного файла или ...
при условии, что ваша оболочка поддерживает подстановку процессов (bash поддерживает).
источник
comm -23
Утилита Unix
diff
предназначена именно для этой цели.См. Руководство и Интернет для получения информации о вариантах, различных форматах вывода и т. Д.
источник
Рассмотрим это:
файл a.txt:
файл b.txt:
Вы можете найти разницу с:
Результат будет:
Вы можете перенаправить вывод в выходной файл (c.txt), используя:
Это ответит на ваш вопрос:
источник
-d
, что сделаетdiff
все возможное, чтобы найти наименьшее возможное различие.-i
,-E
,-w
,-B
И--suppress-blank-empty
также может быть полезно время от времени, хотя и не всегда. Если вы не знаете, что подходит вашему варианту использования, попробуйтеdiff --help
сначала (что обычно является хорошей идеей, если вы не знаете, что может делать команда).Иногда
diff
это именно та утилита, которая вам нужна, но иногдаjoin
более подходящая. Файлы должны быть предварительно отсортированы или, если вы используете оболочку, которая поддерживает подстановку процессов, такую как bash, ksh или zsh, вы можете выполнять сортировку на лету.источник
Пытаться
У меня это обычно работает намного лучше в большинстве случаев. Вы можете предварительно отсортировать файлы, если порядок строк не важен (например, некоторые текстовые файлы конфигурации).
Например,
источник
sdiff <(sort file1) <(sort file2)
)Если вам нужно решить эту проблему с помощью coreutils, принятый ответ хорош:
Вы также можете использовать sd (stream diff), который не требует сортировки или подстановки процессов и поддерживает бесконечные потоки, например:
Возможно, не так много пользы в этом примере, но все же учтите это; в некоторых случаях вы не сможете использовать
comm
ниgrep -F
ниdiff
.Вот пост в блоге, который я написал о различиях между потоками на терминале, который представляет sd.
источник
Но нет
grep
решения?строки, которые существуют только в файле2:
строки, которые существуют только в file1:
строки, которые существуют в обоих файлах:
источник
Уже много ответов, но ИМХО ни один из них не идеален. Ответ Танатоса оставляет несколько дополнительных символов в строке, а ответ Сорпигала требует, чтобы файлы были отсортированы или предварительно отсортированы, что может быть неадекватным во всех обстоятельствах.
Я думаю , что лучший способ получения линий , которые не отличаются , и больше ничего (никаких дополнительных символов, без повторного заказа) представляет собой комбинацию
diff
,grep
иawk
(или аналогичный).Если в строках нет символа «<», коротким однострочником может быть:
но это удалит все экземпляры «<» (меньше, чем пробел) из строк, что не всегда нормально (например, исходный код). Самый безопасный вариант - использовать awk:
Этот однострочник сравнивает оба файла, затем отфильтровывает вывод diff в стиле ed, а затем удаляет завершающий "<", который добавляет diff. Это работает, даже если в самих строках есть «<».
источник
Я удивлен, что никто не упомянул
diff -y
о параллельном выводе , например:И в
file3
(разные строки имеют символ|
посередине):источник
Используйте утилиту Diff и извлекайте только строки, начинающиеся с <в выводе
источник
Я перепробовал почти все ответы в этой теме, но ни один из них не был полным. После нескольких трасс выше один работал у меня. diff даст вам разницу, но с некоторыми нежелательными специальными характеристиками. где ваши фактические разностные линии начинаются с '>'. так что следующий шаг - строки grep начинаются с '>', а затем удаляются с помощью sed .
источник
<
. Вы увидите это, если поменяете порядок входных файлов. Даже если бы вы сделали это, вы бы предпочли опуститьgrep
, используя больше sed: `diff a1 a2 | sed '/> / s ///' `Это может привести к разрыву строк, содержащих>
или<
в правильной ситуации, и по- прежнему оставлять лишние строки, описывающие номера строк. Если вы хотите попробовать этот подход лучше всего было бы:diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'
.Вы можете использовать
diff
следующее форматирование вывода:--old-line-format=''
, отключите вывод для файла1, если строка отличается от сравнения в файле2.--unchanged-line-format=''
, отключите вывод, если строки совпадают.источник
Если у вас есть файл CSV с одним или даже несколькими столбцами , вы можете выполнять эти построчные операции «diff», используя встроенную базу данных sqlite3. Он поставляется с питоном, поэтому должен быть доступен на большинстве Linux / Mac. Вы можете создать сценарий команд sqlite3 в оболочке bash без необходимости писать python.
Примечание: Убедитесь , что существует новая строка для каждой из команд sqlite3.
Как это устроено
Если вам нужно работать с конкретными столбцами, вам подойдет sqlite3 или любой db.
Я пробовал различать несколько файлов GB, используя встроенные инструменты diff и comm. Sqlite на милю превосходит утилиты Linux.
источник