Grep сравнить два файла
Иногда возникает необходимость сравнить несколько файлов между собой. Это может понадобиться при анализе разницы между несколькими версиями конфигурационного файла или просто для сравнения различных файлов. В Linux для этого есть несколько утилит, как для работы через терминал, так и в графическом интерфейсе.
В этой статье мы рассмотрим как выполняется сравнение файлов Linux. Разберем самые полезные способы, как для терминала, так и в графическом режиме. Сначала рассмотрим как выполнять сравнение файла linux с помощью утилиты diff.
5. Поиск в подкаталогах
Часто требуется выполнить поиск файлов не только в текущем рабочем каталоге, но и в подкаталогах. G rep позволяет это сделать с помощью флага -r:
Как можно заметить, grep проходит через каждый подкаталог внутри текущего каталога и перечисляет файлы и строки, в которых найдено совпадение.
4. KDiff3
KDiff3 - еще один отличный, свободный инструмент для сравнения файлов в окружении рабочего стола KDE. Он входит в набор программ KDevelop и работает на всех платформах, включая Windows и MacOS. Можно выполнить сравнение до трех файлов Linux или даже сравнить каталоги. Кроме того, есть поддержка слияния и ручного выравнивания.
10. Список имен файлов
Чтобы напечатать только имя файлов, в которых найден шаблон, используйте флаг -l:
7. Печать номеров строк
Если хотите напечатать номера найденных строк, чтобы узнать их позицию в файле, используйте опцию -n:
14. Файл шаблонов
Если у вас есть некий список часто используемых шаблонов, укажите его в файле и используйте флаг -f. Файл должен содержать по одному шаблону на строку.
В примере мы создали файл шаблонов pattern.txt с таким содержанием:
Чтобы это использовать, применяйте ключ -f:
2. Meld
Это легкий инструмент для сравнения и объединения файлов. Он позволяет сравнивать файлы, каталоги, а также выполнять функции системы контроля версий. Программа создана для разработчиков и позволяет сравнивать до трёх файлов. Можно сравнивать каталоги и автоматически объединять сравниваемые файлы. Кроме того поддерживаются такие системы контроля версий, как Git.
Синтаксис команды
Grep ожидает шаблон и необязательные аргументы вместе со списком файлов, если они используются без конвейера.
12. Совпадение по началу строки
Используя регулярные выражения, можно найти начало строки:
Обратите внимание, как использование символа «^» изменяет выходные данные. Знак «^» указывает начало строки, т.е. ^It соответствует любой строке, начинающейся со слова It. Заключение в кавычки может помочь, когда шаблон содержит пробелы и т. д.
1. Kompare
Kompare - это графическая утилита для работы с diff, которая позволяет находить отличия в файлах, а также объединять их. Написана на Qt и рассчитана в первую очередь на KDE. Кроме сравнения файлов утилита поддерживает сравнение каталогов и позволяет создавать и применять патчи к файлам.
Заключение
Приведенные выше примеры – лишь верхушка айсберга. G rep поддерживает целый ряд опций и может оказаться полезным инструментом в руках специалиста, который способен эффективно его использовать. Мы можем не только взять на вооружение приведенные выше примеры, но и комбинировать их, чтобы получить требуемый результат в различных условиях.
Для дальнейшего изучения утилиты и расширения кругозора стоит почитать мануал, выполнив в терминале команду man grep, или посетить страницу с официальной документацией .
Есть два файла, называемые «a.txt» и «b.txt», оба содержат список слов. Теперь я хочу проверить, какие слова лишние в «a.txt», а какие нет в «b.txt» .
Мне нужен эффективный алгоритм, так как мне нужно сравнить два словаря.
если у вас установлен vim, попробуйте следующее:
вы найдете это фантастическим.
Ваш ответ потрясающий, но мой учитель потребовал, чтобы я не использовал какие-либо библиотечные функции: P
Сортируйте их и используйте comm :
comm сравнивает (отсортированные) входные файлы и по умолчанию выводит три столбца: строки, уникальные для a, строки, уникальные для b, и строки, которые присутствуют в обоих. Указав -1 , -2 и / или -3 вы можете подавить соответствующий вывод. Поэтому comm -23 a b перечисляются только записи, уникальные для. Я использую <(. ) синтаксис для сортировки файлов на лету, если они уже отсортированы, вам это не нужно.
@AliImran comm более эффективен, потому что он выполняет задание за один запуск, не сохраняя весь файл в памяти. Поскольку вы используете словари, которые, скорее всего, уже отсортированы, они вам даже не нужны sort . С grep -f file1 file2 другой стороны, использование будет загружать все file1 в память и сравнивать каждую строку file2 со всеми этими записями, что намного менее эффективно. В основном это полезно для небольших, несортированных -f file1 .
Спасибо @AndersJohansson за то, что поделились командой "comm". Это действительно здорово. Мне часто приходится выполнять внешние соединения между файлами, и это помогает.
Обратите внимание на символ новой строки . Я только что обнаружил, что \n он также будет включен для сравнения.
Если вы предпочитаете стиль вывода diff от git diff , вы можете использовать его с --no-index флагом для сравнения файлов не в репозитории git:
Используя пару файлов с примерно 200 тыс. Строк имен файлов в каждом, я протестировал (с помощью встроенной time команды) этот подход по сравнению с некоторыми другими ответами здесь:
comm кажется самым быстрым на сегодняшний день, но git diff --no-index кажется самым быстрым подходом для вывода в стиле diff.
This form is to compare the given two paths on the filesystem. You can omit the --no-index option when running the command in a working tree controlled by Git and at least one of the paths points outside the working tree, or when running the command outside a working tree controlled by Git.
Я хочу сравнить файл1 с файлом2 и создать файл3, содержащий строки в файле1, которых нет в файле2.
Я пробовал diff, но он генерирует некоторые числа и другие символы перед разными строками, что затрудняет сравнение файлов.
diff (1) - это не ответ, но comm (1) - это ответ.
при условии, что ваша оболочка поддерживает подстановку процессов (bash поддерживает).
Что значит «отсортировано»? Что строки имеют одинаковый порядок? Тогда это, вероятно, нормально для большинства случаев использования - например, проверка того, какие строки были добавлены, путем сравнения с резервной более старой версией. Если вновь добавленные строки не могут находиться между существующими строками, это большая проблема.
@EgorHans: если в файле есть, например, строки, содержащие целые числа, такие как «3 \ n1 \ n3 \ n2 \ n», строки должны быть сначала переупорядочены в порядке возрастания или убывания, например, «\ 1 \ n2 \ n3 \ n3 \ n» с дубликатами. соседний. Это «отсортировано», и оба файла должны быть отсортированы аналогичным образом. Когда в новом файле есть новые строки, не имеет значения, находятся ли они «между существующими строками», потому что после сортировки их нет, они отсортированы.
Утилита Unix diff предназначена именно для этой цели.
См. Руководство и Интернет для получения информации о вариантах, различных форматах вывода и т. Д.
Это не выполняет запрошенную работу; он вставляет кучу дополнительных символов даже с использованием переключателей командной строки, предложенных в других ответах.
Рассмотрим это:
файл a.txt:
Вы можете найти разницу с:
Это ответит на ваш вопрос:
". which contains the lines in file1 which are not present in file2."
У этого ответа есть два ограничения: (1) он работает только для коротких строк (по умолчанию менее 80 символов, хотя это можно изменить) и, что более важно, (2) он добавляет "
Во многих случаях вы также захотите использовать -d , что сделает diff все возможное, чтобы найти наименьшее возможное различие. -i , -E , -w , -B И --suppress-blank-empty также может быть полезно время от времени, хотя и не всегда. Если вы не знаете, что подходит вашему варианту использования, попробуйте diff --help сначала (что обычно является хорошей идеей, если вы не знаете, что может делать команда).
Кроме того, используя --line-format =% L, вы удерживаете diff от генерации каких-либо дополнительных символов (по крайней мере, в справке сказано, что это работает так, но мы собираемся попробовать).
Иногда diff это именно та утилита, которая вам нужна, но иногда join более подходящая. Файлы должны быть предварительно отсортированы или, если вы используете оболочку, которая поддерживает подстановку процессов, такую как bash, ksh или zsh, вы можете выполнять сортировку на лету.
Но grep решения нет ?
строки, которые существуют только в файле2:
строки, которые существуют только в file1:
строки, которые существуют в обоих файлах:
Идеально! Обратите внимание, эти команды могут занять 10+ секунд, если ваши два файла большие (15k + строк). Спасибо!
У меня это обычно работает намного лучше в большинстве случаев. Вы можете предварительно отсортировать файлы, если порядок строк не важен (например, некоторые текстовые файлы конфигурации).
Хорошая утилита! Мне нравится, как он отмечает отличительные линии. Значительно упрощает сравнение конфигураций. Вместе с sort это смертельная комбинация (например sdiff <(sort file1) <(sort file2) )
Если вам нужно решить эту проблему с помощью coreutils, принятый ответ хорош:
Вы также можете использовать sd (stream diff), который не требует сортировки или подстановки процессов и поддерживает бесконечные потоки, например:
Вероятно, не так много пользы в этом примере, но все же учтите это; в некоторых случаях вы не сможете использовать comm ни grep -F ни diff .
Вот пост в блоге, который я написал о различиях потоков на терминале, который представляет sd.
Я думаю , что лучший способ получения линий , которые не отличаются , и больше ничего (никаких дополнительных символов, без повторного заказа) представляет собой комбинацию diff , grep и awk (или аналогичный).
Этот однострочник сравнивает оба файла, затем отфильтровывает вывод diff в стиле ed, а затем удаляет завершающий "
comm не требует сортировки (в более новых версиях?) - просто используйте --nocheck-order. Я часто использую это при манипулировании csvs из интерфейса командной строки.
Вы можете использовать diff следующее форматирование вывода:
--old-line-format='' , отключите вывод для файла1, если строка отличается от сравнения в файле2.
--unchanged-line-format='' , отключите вывод, если строки совпадают.
Воспользуйтесь утилитой Diff и извлеките из вывода только строки, начинающиеся с
Я перепробовал почти все ответы в этой теме, но ни один из них не был полным. После нескольких трасс, описанных выше, у меня сработало. diff даст вам разницу, но с некоторыми нежелательными специальными характеристиками. где ваши фактические строки разницы начинаются с '>'. так что следующий шаг - строки grep начинаются с '>' и затем удаляются с помощью sed .
Это плохая идея. Вам также потребуется изменить строки, начинающиеся с < . Вы увидите это, если поменяете порядок входных файлов. Даже если бы вы сделали это, вы бы предпочли опустить grep , используя больше sed: `diff a1 a2 | sed '/>/ s ///' `Это может по-прежнему разрывать строки, содержащие > или < в правильной ситуации, и по- прежнему оставляет дополнительные строки, описывающие номера строк. Если вы хотите попробовать этот подход лучше всего было бы: diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p' .
Я удивлен, что никто не упомянул diff -y о параллельном выводе , например:
И в file3 (разные строки имеют символ | посередине):
Если у вас есть CSV-файл с одним или даже несколькими столбцами , вы можете выполнять эти построчные операции "diff", используя встроенную базу данных sqlite3. Он поставляется с питоном, поэтому должен быть доступен на большинстве Linux / Mac. Вы можете создавать сценарии команд sqlite3 в оболочке bash без необходимости писать python.
- Создайте файлы a.csv и b.csv
- Убедитесь, что sqlite3 установлен с помощью команды "sqlite3 -help"
- Выполните приведенные ниже команды непосредственно в оболочке Linux / Mac (или поместите ее в сценарий)
Примечание: Убедитесь , что существует новая строка для каждой из команд sqlite3.
Как это работает
- Импортируйте 2 CSV в таблицы «atable» и «btable» соответственно.
- Используйте оператор sql « except », чтобы выбрать данные, доступные в «atable», но отсутствующие в «btable». Создайте таблицу «результатов» с помощью оператора запроса select.
- Выведите таблицу результатов в result.csv, выполнив команду «select * from result;»
Если вам нужно работать с определенными столбцами, вам подойдет sqlite3 или любой db.
Я пробовал различать несколько файлов GB, используя встроенные инструменты diff и comm. Sqlite на милю превосходит утилиты Linux.
4. Проверка количества совпадений
Иногда вместо фактического совпадения со строкой нам необходимо количество успешных совпадений, найденных grep. Этот результат можно получить, используя опцию -c:
13. Совпадение по концу строки
Эта полезная регулярка способна помочь найти по шаблону конец строки:
Обратите внимание, как меняется вывод, когда мы сопоставляем символ «.» и когда используем «$», чтобы сообщить утилите о строках, заканчивающихся на «.» (без тех, которые могут содержать символ посередине).
8. Ограниченный вывод
Для больших файлов вывод может быть огромным и тогда вам понадобится фиксированное количество строк вместо всей простыни. Можно использовать -m[num]:
Обратите внимание, как использование флага влияет на вывод для того же набора условий:
11. Точный вывод строк
Если необходимо напечатать строки, которые точно соответствуют заданному шаблону, а не какой-то его части, применяйте в команде ключ -x:
В приведенном ниже примере file.txt содержится слово «support», а строки без точного совпадения игнорируются.
1. Поиск в нескольких файлах
Grep позволяет искать заданный шаблон не только в одном, но и в нескольких файлах с помощью масок (например, знака «*»):
Из приведенного вывода можно заметить, что grep печатает имя файла перед соответствующей строкой, чтобы указать местонахождение шаблона.
16. Расширенные выражения
G rep поддерживает расширенные регулярные выражения или ERE (похожие на egrep) с использованием флага -E.
Использование ERE имеет преимущество, когда вы хотите рассматривать мета-символы как есть и не хотите заменять их строками. Использование -E с grep эквивалентно команде egrep.
15. Указание нескольких шаблонов
G rep позволяет указать несколько шаблонов с помощью -e:
3. Diffuse
Diffuse - еще один популярный и достаточно простой инструмент для сравнения и слияния файлов. Он написан на Python 2. Поэтому в современных версиях Ubuntu программу будет сложно установить. Поддерживается две основные возможности - сравнение файлов и управление версиями. Вы можете редактировать файлы прямо во время просмотра.
Сравнение файлов Linux с помощью GUI
Существует несколько отличных инструментов для сравнения файлов в linux в графическом интерфейсе. Вы без труда разберетесь как их использовать. Давайте рассмотрим несколько из них:
3. Поиск всего слова
Зачастую вместо частичного совпадения необходимо полное соответствие поисковому слову. Это можно сделать, используя флаг -w:
5. TkDiff
Это очень простая утилита для сравнения файлов написанная на основе библиотеки tk. Она позволяет сравнивать только два файла, поддерживает поиск и редактирование сравниваемых файлов.
6. Инверсивный поиск
Если вы хотите найти что-то несоответствующее заданному шаблону, grep и это умеет при помощи флага -v:
Можно сравнить вывод команды grep по одному и тому же шаблону и файлу с флагом -v или без него. С флагом печатается каждая строка, которая не соответствует шаблону.
Выводы
В этой статье мы рассмотрели как выполняется сравнение файлов linux с помощью терминала, как создавать патчи, а также сделали небольшой обзор лучших графических утилит для сравнения файлов. А какие инструменты для сравнения используете вы? Напишите в комментариях!
помогите сделать быстрее, или раскритикуйте вдребезги мой нубовской подход, прошу толчек в нужном направлении.
P.S. если бы не нужно было вывыодить всю строку из файла 2 проблема думаю решилась бы с помощю
comm -2 file1 file2 > file3 но не факт :)
- Вопрос задан более трёх лет назад
- 2472 просмотра
Оценить 1 комментарий
нужно во втором файле найти строки (и вывести всю строку в файл) у которых совпадает $1 и $3 но другой $6
в первойм файле $6=q1 во втором $6=q1-q3
столбец $1 всегда начинается с 9
Это не описание, а какая-то ахинея, по которой можно написать сто разных программ.
Приведи лучше уменьшенные исходные файлы (по паре строк каждый) и файл с результатом, который должен из них получиться.
Укажите первым файлом тот, что поменьше.
первым проходом выделяем из второго файла все строки, в которых есть совпадения по первому столбцу, вторым проходом выделяем совпадения по третьему столбцу, третьим исключаем ненужное по 6-му столбцу.
если можно - примеры файлов по несколько сотен строк дайте мылом, попробую написать
Простите не совсем точно обяснил
в 1 файле 1 столбец уникальный таких записей милинон 3й столбец не уникальный на милион уникальных где то 2000(мешать нельзя, и во втором файле есть много записей $1 но с другими $3 и $6)
вот а теперь нужно взять вот это сочетание $1 и $3 найти его в 2 файле и отбросить те где $6=q1 а результат в файл
к сожелению поэтапность тут не поможет(((((
cat /tmp/file22.txt | awk -F"," '
эта команда какраз и делает то что вы предложили берет 1 и 3 столбцы из 1 файла и значение для 6 столбца и ищет их в файле 2
Строки с несовпадающим $6 вы уже выкинули.
Перегоняем оба файла в формат $1,$3, отбрасывая прочую информацию и убирая дубли.
Сортируем, находим пересечение этих файлов.
Перегоняем второй в формат $1,$3,$2,$4,$5,$6,$7 и сортируем.
На своем любимом языке программирования открываем этот файл (1) и файл пересечений (2), сравнивая текущую строку в файле (2) с началом текущей строки в файле (1).
Если они совпадают - выводим, переставив столбцы.
Если нет - читаем следующую строку из файла, строка в котором оказалась меньше другого (данные-то отсортированы).
В один проход получаем результат, никаких недель.
Огромное спасибо за идеи по решению, решил осваивать perl =)
Сергей спасибо вам . немного почитал переделал и вуаля готово)))
Adamos Руслан Федосеев и вам спасибо применил ваши советы для предварительной подготовки файла к запуску основного скрипта в других его вариациях (не представленно ниже)
а чем не подошел мой вариант с ассоциативными массивами? При использовании ассоциативных массивов, вам не нужно выполнять полный перебор, код выглядит гораздо меньше и более читабельным, ну и вообще быстрее работает, меньше памяти требует.
Ваш вариант мне очень понравился но он не работал, возможно я не совсем правильно понял как это работает
дело в том что мне нужно сравнить:
есть 2 файла в каждом 5 столбцов
мне нужно взять n-й елемент первого столбца сравнить его со всеми значениями первого столбца втогого файла
если да то тогда сравнить 3 если да то тогда сравнить 4 если нет тогда на печать
if ($a0==$a1 && $c0==$c1 && $d0==$d1) print
Если это можно сделать с помощю "ассоциативными массивами" будет очень круто но вот применил и
х на практике и данные неверные получаю
Та были использованы ассоциативные массивы.
То есть вместо числового индекса элемента, я использую значение первого столбца как индекс, и мне не нужно выполнять поиск по всем элементам - само значение элемента и есть индекс, и я сравниваю только 3 и 4 столбец, без поиска элементов.
А не работать оно может, если у вас в первом столбце не уникальные значения, то есть если они могут повторяться. Тогда да, будут перезаписываться и логика нарушается, и мой вариант нужно дорабатывать. Но если ваш код работает, то никаких проблем. Перл полезен чтобы затыкать дырки ), хотя я бы рекомендовал использовать более интуитивно-понятные имена переменных, иначе через 2-3 недели вы сами в нем не разберетесь.
Да, значения первого столбца не уникальные, болше того они повторяются раз на 5-10 милионов, значения 3 и 5 столбика тоже повторяются но чаще
по поводу названий масивов согласен у меня там коментарии стоят(чтобы не забыть) использую обезличивание потому как нужен скрипт шаблон для 6 похожих задач
как решить это с помощью ассоциативных массивов?
Добавить в начало порядковый номер строки и использовать его как индификатор строки?
прочитал мануалы и сделал с помощью ассоциативных массивов, обработка милиарда значений происходит в 4 раза быстрее))))
Эта популярная утилита умеет не только искать в файле соответствующие шаблону строки. Рассмотрим некоторые из часто используемых в различных ситуациях опций grep, которые пригодятся сисадмину и разработчику.
Перевод публикуется с сокращениями, автор оригинальной статьи Abhishek Nair .
Название утилиты расшифровывается как Globally search for a REgular expression and Print matching lines. Grep в основном ищет заданный шаблон или регулярное выражение из стандартного ввода или файла и печатает соответствующие заданным критериям строки. Он часто используется для фильтрации ненужных деталей при выводе только необходимой информации из больших файлов журналов.
Мощь регулярных выражений в сочетании с поддерживаемыми опциями в grep делает это возможным.
Сравнение файлов diff
Утилита diff linux - это программа, которая работает в консольном режиме. Ее синтаксис очень прост. Вызовите утилиту, передайте нужные файлы, а также задайте опции, если это необходимо:
$ diff опции файл1 файл2
Можно передать больше двух файлов, если это нужно. Перед тем как перейти к примерам, давайте рассмотрим опции утилиты:
- -q - выводить только отличия файлов;
- -s - выводить только совпадающие части;
- -с - выводить нужное количество строк после совпадений;
- -u - выводить только нужное количество строк после отличий;
- -y - выводить в две колонки;
- -e - вывод в формате ed скрипта;
- -n - вывод в формате RCS;
- -a - сравнивать файлы как текстовые, даже если они не текстовые;
- -t - заменить табуляции на пробелы в выводе;
- -l - разделить на страницы и добавить поддержку листания;
- -r - рекурсивное сравнение папок;
- -i - игнорировать регистр;
- -E - игнорировать изменения в табуляциях;
- -Z - не учитывать пробелы в конце строки;
- -b - не учитывать пробелы;
- -B - не учитывать пустые строки.
Это были основные опции утилиты, теперь давайте рассмотрим как сравнить файлы Linux. В выводе утилиты кроме, непосредственно, отображения изменений, выводит строку в которой указывается в какой строчке и что было сделано. Для этого используются такие символы:
К тому же, линии, которые отличаются, будут обозначаться символом .
Вот содержимое наших тестовых файлов:
Теперь давайте выполним сравнение файлов diff:
diff file1 file2
В результате мы получим строчку: 2,3c2,4. Она означает, что строки 2 и 3 были изменены. Вы можете использовать опции для игнорирования регистра:
diff -i file1 file2
Можно сделать вывод в две колонки:
diff -y file1 file2
А с помощью опции -u вы можете создать патч, который потом может быть наложен на такой же файл другим пользователем:
diff -u file1 file2
Чтобы обработать несколько файлов в папке удобно использовать опцию -r:
diff -r ~/tmp1 ~/tmp2
diff -u file1 file2 > file.patch
Как видите, все очень просто. Но не очень удобно. Более приятно использовать графические инструменты.
2. Поиск без учета регистра
G rep предлагает искать паттерн, не глядя на его регистр. Используйте флаг -i, чтобы утилита игнорировала регистр:
9. Отображение дополнительных строк
Иногда необходимо вывести не только строки по некоторому шаблону, но и дополнительные строки выше или ниже найденных для понимания контекста. Можно напечатать строку выше, ниже или оба варианта, используя флаги -A, -B или -C со значением num (количество дополнительных строк, которые будут напечатаны). Это применимо ко всем совпадениям, которые grep находит в указанном файле или в списке файлов.
Ниже показан обычный вывод grep , а также вывод с флагами. Обратите внимание, как grep интерпретирует флаги и их значения, а также изменения в соответствующих выходных данных:
- с флагом -A1 выведется 1 строка, следующая за основной;
- -B1 напечатает 1 строку перед основной;
- -C1 выведет по одной строке снизу и сверху.
Читайте также: