2

У меня есть 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
    

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

1 ответ1

5

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

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

С помощью diff -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 в своем входном файле.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .