linux awk сравнивает два CSV-файла и создает новый файл с флагом - PullRequest
3 голосов
/ 02 марта 2012

У меня есть 2 CSV-файла, которые мне нужно сравнить и получить разницу с недавно отформатированным файлом. Образцы приведены ниже.

СТАРЫЙ файл

DTL,11111111,1111111111111111,11111111111,Y,N,xx,xx
DTL,22222222,2222222222222222,22222222222,Y,Y,cc,cc
DTL,33333333,3333333333333333,33333333333,Y,Y,dd,dd
DTL,44444444,4444444444444444,44444444444,Y,Y,ss,ss
DTL,55555555,5555555555555555,55555555555,Y,Y,qq,qq

НОВЫЙ файл

DTL,11111111,1111111111111111,11111111111,Y,Y,xx,xx
DTL,22222222,2222222222222222,22222222222,Y,N,cc,cc
DTL,44444444,4444444444444444,44444444444,Y,Y,ss,ss
DTL,55555555,5555555555555555,55555555555,Y,Y,qq,qq
DTL,77777777,7777777777777777,77777777777,N,N,ee,ee

Выходной файл

Я хочу сравнить старые и новые файлы CSV и найти изменения, которые произошли в новом файле, и ОБНОВИТЬ ФЛАГ для обозначения этих изменений

U - если новая запись файла ОБНОВЛЕНА D - если запись, существующая в старом файле, удаляется в новом файле N - если запись, существующая в новом файле, недоступна в старом файле

Пример выходного файла:

DTL,11111111,1111111111111111,11111111111,Y,Y,xx,xx U
DTL,22222222,2222222222222222,22222222222,Y,N,cc,cc U
DTL,33333333,3333333333333333,33333333333,Y,Y,dd,dd D
DTL,77777777,7777777777777777,77777777777,N,N,ee,ee N

Я использовал команду diff, но она также будет повторять ОБНОВЛЕННУЮ запись, чего я не хочу.

 DTL,11111111,1111111111111111,11111111111,Y,N,xx,xx
 DTL,22222222,2222222222222222,22222222222,Y,Y,cc,cc
 DTL,33333333,3333333333333333,33333333333,Y,Y,dd,dd
  ---
 DTL,11111111,1111111111111111,11111111111,Y,Y,xx,xx
 DTL,22222222,2222222222222222,22222222222,Y,N,cc,cc
 5a5
 DTL,77777777,7777777777777777,77777777777,N,N,ee,ee

Я также использовал однострочную команду AWK для фильтрации своих записей

 awk 'NR==FNR{A[$1];next}!($1 in A)' FS=: old.csv new.csv

проблема в том, что я не получаю записи, относящиеся только к старому файлу. что

DTL,33333333,3333333333333333,33333333333,Y,Y,dd,dd

Я также запустил управляемый сценарий bash, чтобы добиться этого, но не нашел большой помощи в хорошем примере.

 myscript.awk

BEGIN { 
        FS = ","    # input field seperator 
        OFS = ","   # output field seperator
}

NR > 1 {
    #flag 
    # N - new record  D- Deleted U - Updated

id = $1
    name = $2
    flag = 'N'

   # This prints the columns in the new order. The commas tell Awk to use the     character set in OFS
    print id,name,flag
}

 >> awk -f  myscript.awk  old.csv new.csv > formatted.csv

Ответы [ 2 ]

6 голосов
/ 02 марта 2012

Это может работать для вас:

diff  -W999 --side-by-side OLD NEW |
sed '/^[^\t]*\t\s*|\t\(.*\)/{s//\1 U/;b};/^\([^\t]*\)\t*\s*<$/{s//\1 D/;b};/^.*>\t\(.*\)/{s//\1 N/;b};d'
DTL,11111111,1111111111111111,11111111111,Y,Y,xx,xx U
DTL,22222222,2222222222222222,22222222222,Y,N,cc,cc U
DTL,33333333,3333333333333333,33333333333,Y,Y,dd,dd D
DTL,77777777,7777777777777777,77777777777,N,N,ee,ee N

решение awk в том же духе:

diff -W999 --side-by-side OLD NEW |
awk '/[|][\t]/{split($0,a,"[|][\t]");print a[2]" U"};/[\t] *<$/{split($0,a,"[\t]* *<$");print a[1]" D"};/>[\t]/{split($0,a,">[\t]");print a[2]" N"}'
DTL,11111111,1111111111111111,11111111111,Y,Y,xx,xx U
DTL,22222222,2222222222222222,22222222222,Y,N,cc,cc U
DTL,33333333,3333333333333333,33333333333,Y,Y,dd,dd D
DTL,77777777,7777777777777777,77777777777,N,N,ee,ee N
2 голосов
/ 02 марта 2012

Хорошей отправной точкой, вероятно, будет:

 diff -e OLD NEW

Это выводит:

 5a
 DTL,77777777,7777777777777777,77777777777,N,N,ee,ee
 .
 1,3c
 DTL,11111111,1111111111111111,11111111111,Y,Y,xx,xx
 DTL,22222222,2222222222222222,22222222222,Y,N,cc,cc

Это означает, что он добавил запись в строке 5 (5a) и изменил записи в строках 1 и 3 (1,3c).

Если вы не можете использовать этот формат как есть (что было бы хорошо, если бы вы использовали стандарт), вам нужно написать скрипт, который преобразует его в формат, который вы описываете.

...