Используя Разность на определенном столбце в файле

Попробуйте что-то как SystemRescueCD. Должен сделать то, в чем Вы нуждаетесь (скопируйте один жесткий диск в другого с минимальными издержками).

Кроме того, если CD/DVD-привод так же стар как остальная часть системы, Вы загружаетесь на, это, вероятно, довольно медленно, и загружающийся от CD.... будет еще медленнее. Попытайтесь установить свою спасательную систему на каком-то флеш-накопителе. Это будет намного быстрее, чем начальная загрузка с CD (это предполагает, что можно загрузиться от USB в старой системе).

6
18.12.2014, 00:06
2 ответа

awk - это лучший инструмент для сравнения столбцов файлов. См., например, ответ на: сравните две колонки разных файлов и распечатайте, если они совпадают -- существуют похожие ответы для распечатки строк для совпадения колонок.

Поскольку необходимо распечатать строки, которые не совпадают с , мы можем создать команду awk, которая распечатает строки в файле2, для которых в столбце 2 в файле1 было указано , а не :

$ awk 'NR==FNR{c[$2]++;next};c[$2] == 0' file1 file2
Another   193 stuff2
Another   783 stuff3

Как аналогично объяснил Тердон в вышеупомянутом вопросе,

  • NR==FNR : NR - это номер текущей входной строки, а FNR - номер строки текущего файла. Эти две строки будут равны только во время чтения 1-го файла.
  • c[$2]++; next : если это 1-й файл, сохраните 2-е поле в массиве c. Затем перейдите к следующей строке, чтобы она была применена только к 1-му файлу.
  • c[$2] == 0 : оставшийся блок будет выполнен только в том случае, если это второй файл, поэтому мы проверяем, было ли уже видно поле 2 этого файла (c[$2]==0), и если да, то выводим строку. В awk по умолчанию выводится строка, поэтому если c[$2]==0 верно, то строка будет выведена.

Но вам также нужны строки из файла 1, для которых колонка 2 не совпадает в файле 2. Это можно получить, просто обменяв их положение одной и той же командой:

$ awk 'NR==FNR{c[$2]++;next};c[$2] == 0' file2 file1
Something  456 item2
Something  768 item3

Так что теперь вы можете сгенерировать нужный вывод, используя awk дважды. Возможно, кто-то с большим опытом работы с awk может сделать это за один проход.

Вы пометили свой вопрос с помощью /ksh, так что я предполагаю, что вы используете оболочку korn. В ksh вы можете определить функцию для вашего diff, скажем diffcol2, чтобы сделать вашу работу проще:

diffcol2()
{
   awk 'NR==FNR{c[$2]++;next};c[$2] == 0' $2 $1      
   awk 'NR==FNR{c[$2]++;next};c[$2] == 0' $1 $2      
}

У этого есть поведение, которое вы хотите:

$ diffcol2 file1 file2
Something  456 item2
Something  768 item3
Another   193 stuff2
Another   783 stuff3
9
27.01.2020, 20:23

Я не думаю, что diff (даже в сочетании с вырезанием) будет достаточно гибким, чтобы справиться с этим. И кажется, что на самом деле вам нужны ключи в file1, которых нет в file2, и наоборот - не строго строчный diff. Если входные файлы большие, я бы выбрал perl, но для маленьких файлов этот скрипт работает на входе при условии:

%cat a. awk

BEGIN {
  while (getline < "file1") {
    line=$0;
    split(line,f," ");
    key=f[2];
    f1[key]=line
  }
  while (getline < "file2") {
    line=$0;
    split(line,f," ");
    key=f[2];
    f2[key]=line
  }
}
END {
  for (c in f1) {
    if (c in f2 == 0) print f1[c]
  }
  for (c in f2) {
    if (c in f1 == 0) print f2[c]
  }
}

И это то, как вы его запускаете (обратите внимание на трюк с /dev/null, так как awk ожидает входной файл в качестве параметра:

%awk -f a.awk /dev/null
Something  456 item2
Something  768 item3
Another   193 stuff2
Another   783 stuff3
3
27.01.2020, 20:23

Теги

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