Различать каждую отдельную строку в первом файле от всех строк во втором файле?

313
IDLacrosseplayer

У меня есть 2 представления TCL проекта, которые генерируются двумя разными версиями одного и того же инструмента, давайте назовем их v1.tclиv2.tcl

Эти журналы обычно логически идентичны для всех намерений и целей, за исключением порядка строк. Каждая строка v1.tclбудет найдена где-то ровно один раз, v2.tclкогда версии 1 и 2 моего проекта идентичны.

Я хотел бы иметь возможность определить, сделал ли кто-то изменение, v2.tclкоторое необходимо перенести в v1.tcl(или наоборот) ... другими словами, я хотел бы видеть только строки, в которых не совпадают. Например:

  1. v1.tcl:

    foo1 bar1 hello1 world1 
  2. v2.tcl:

    hello1 bar1 foo2 world1 goodbye2 
  3. "diff" возвращаемое значение:

    file1:1 foo1 file2:3 foo2 file2:5 goodbye2 

Должен ли я просто написать свой собственный маленький сценарий? Есть ли инструмент, который уже делает это?

2
@PimpJuiceIT Я устал от этого, и так как это код, я иногда получаю ошибки о `grep: Trailing backslash`. Я проверю справочные страницы, чтобы посмотреть, смогу ли я заставить их воспринимать их как текст ... IDLacrosseplayer 5 лет назад 0
@PimpJuiceIT просто запускает ошибки `grep -vf v2.tcl v1.tcl` с" обратной косой чертой ", даже если я перенаправляю их куда-то, как указано выше. IDLacrosseplayer 5 лет назад 0
@PimpJuiceIT Если во входных файлах строки заканчиваются обратной косой чертой, grep выдает ошибки обратной косой черты. Я использовал grep `-F`, чтобы исправить это, и добавил ваш более короткий комментарий / ответ в конец моего. К вашему сведению, я не использовал все решения awk, но добавил bash / cut / grep, чтобы показать имя файла и строки Xen2050 5 лет назад 1
@ Xen2050 Очень хорошее решение, хорошее объяснение всего этого. У меня не было Linux для ssh, чтобы протестировать себя из Linux, так же как и grep, который я комментировал через пакеты Windows GNU или что-то еще. Pimp Juice IT 5 лет назад 0

1 ответ на вопрос

5
Xen2050

Если строки идентичны, и вы хотите знать только , есть ли дополнительные строки в том или ином файле, вы можете использовать sort & diff (и Process Substitution здесь):

$ diff -B <(sort v1.tcl) <(sort v2.tcl) 2c2,3 < foo1 --- > foo2 > goodbye2 

С помощью различий -Bигнорировать пустые строки. Затем вы можете использовать, grep -n [pattern] fileчтобы найти какую линию шаблона находится (возможно, с одним или комбинацией grep, cut, sed, awk), если это имеет значения.

Вот более полный ответ, показывающий номер файла и строки, содержащие совпадения. Не использует sed или awk, просто bash, cut, grep ... вот все (по существу) в одну строку:

diff -B <(sort v1.tcl) <(sort v2.tcl) | while read -r line; do if \ echo "$line" | grep -q "^<"; then grep -F -n -H \ "$(echo "$line"|cut -c3-)" v1.tcl ; elif echo "$line" | grep -q \ "^>"; then grep -F -n -H "$(echo "$line"|cut -c3-)" v2.tcl ; fi done 

Или разбить на несколько строк:

diff -B <(sort v1.tcl) <(sort v2.tcl) | while read -r line do if echo "$line" | grep -q "^<" then grep -F -n -H "$(echo "$line"|cut -c3-)" v1.tcl elif echo "$line" | grep -q "^>" then grep -F -n -H "$(echo "$line"|cut -c3-)" v2.tcl fi done 

И в зависимости от ваших входных файлов (особенно если у вас есть строки с завершающими обратными слешами), я использую эти параметры для чтения и grep:

  • read -r не допускайте обратной косой черты, чтобы избежать каких-либо символов
  • grep -F Интерпретировать PATTERN как список фиксированных строк (вместо регулярных выражений), разделенных символами новой строки, любой из которых должен соответствовать

Кроме того, используя комментарии Pimp Juice IT, если в исходных файлах есть обратная косая черта в конце, то grep выдает ошибку «file: line Trailing backslash». Использование -Fопции grep для очистки ошибки обратной косой черты приводит к гораздо меньшему решению только для grep:

grep -FvHn -f v2.tcl v1.tcl ;grep -FvHn -f v1.tcl v2.tcl 

Использованные параметры grep:

  • -f Получить шаблоны из файла, по одному на строку.
  • -F Интерпретировать PATTERN как список фиксированных строк (вместо регулярных выражений), разделенных символами новой строки, любой из которых должен соответствовать
  • -v Инвертируйте смысл соответствия, чтобы выбрать несовпадающие строки.
  • -H Напечатайте имя файла для каждого совпадения
  • -n Приставьте каждую строку вывода к номеру строки на основе 1 в своем входном файле.
Добро пожаловать :) Задняя обратная косая черта вызывала проблемы с моим первым черновым ответом (без `-F` и я думаю` -r``), хотя образец текста работал нормально, и дополнительные пустые строки вызывали странные проблемы. Но теперь все * кажется * хорошо Xen2050 5 лет назад 0

Похожие вопросы