Различать каждую отдельную строку в первом файле от всех строк во втором файле?
У меня есть 2 представления TCL проекта, которые генерируются двумя разными версиями одного и того же инструмента, давайте назовем их v1.tcl а также v2.tcl
Эти журналы обычно логически идентичны для всех намерений и целей, за исключением порядка строк. Каждая строка в v1.tcl будет найден где-то ровно один раз в v2.tcl когда версии 1 и 2 моего проекта идентичны.
Я хотел бы иметь возможность определить, внес ли кто-то изменения в v2.tcl это должно быть перенесено в v1.tcl (или наоборот) ... другими словами, я хотел бы видеть только строки, в которых не совпадают. Например:
v1.tcl:foo1 bar1 hello1 world1v2.tcl:hello1 bar1 foo2 world1 goodbye2"diff" возвращаемое значение:
file1:1 foo1 file2:3 foo2 file2:5 goodbye2
Должен ли я просто написать свой собственный маленький сценарий? Есть ли инструмент, который уже делает это?
1 ответ
Если строки идентичны, и вы хотите знать только , есть ли дополнительные строки в том или ином файле, вы можете использовать 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 в своем входном файле.