сравнить два файла на уровне ключа (id) и отобразить различия на уровне столбца - PullRequest
2 голосов
/ 20 июня 2019

Я ищу способ сравнить два файла на уровне ключа (id) и отобразить изменения на уровне столбца

file_1.txt  
id|description|name|date  
1|Row 1|a|2019-06-15 00:20:15:00  
2|Row 2|b|2019-06-16 15:18:10:00  
3|Row 3|c|2019-06-17 07:02:17:00  
4|Row 4|d|2019-06-25 09:00:01:00  
5|Row 5|e|2019-06-25 22:00:00:00  


file_2.txt  
id|description|name|date  
1|Row 1|a|2019-06-15 00:20:15:00  
2|Row 2|c|2019-06-16 15:18:10:00  
4|Row 4|d|2019-06-25 09:00:01:00  
5|ROW 5|b|2019-06-25 22:00:00:00  
7|Row 7|f|2019-06-17 07:02:17:00  

Вывод должен выглядеть следующим образом:

1|Row 1|a|2019-06-15 00:20:15:001|Row 1|a|2019-06-15 00:20:15:00,Match  
2|Row 2|c|2019-06-16 15:18:10:00|Row 2|b|2019-06-16 15:18:10:00No Match  
3|Row 3|c|2019-06-17 07:02:17:00,No Match  
4|Row 4|d|2019-06-25 09:00:01:004|Row 4|d|2019-06-25 09:00:01:00,Match  
5|ROW 5|b|2019-06-25 22:00:00:00|Row 5|e|2019-06-25 22:00:00:00,No Match  
7|Row 7|f|2019-06-17 07:02:17:00,No Match  

попытался использовать ниже, где file2 используется в качестве файла драйвера для набора выходных данных, поэтому он не печатает и игнорирует строку с идентификатором 3, поскольку его нет в file2.txt

awk -F, 'NR==FNR{ arr[$1]=$0; next } { print $0 (arr[$1]==$0?arr[$1]",Match":arr[$1]",No Match") }' OFS=, file1.txt file2.txt

id | description | name |дата, Матч
1 | Строка 1 | a | 2019-06-15 00: 20: 15: 001 | Строка 1 | a | 2019-06-15 00: 20: 15: 00, Матч
2 |Строка 2 | c | 2019-06-16 15: 18: 10: 00, без матча
4 | Строка 4 | d | 2019-06-25 09: 00: 01: 004 | Строка 4 | d | 2019-06-25 09: 00: 01: 00, Матч
5 | ROW 5 | b | 2019-06-25 22: 00: 00: 00, Матч отсутствует
7 | Строка 7 | f | 2019-06-17 07: 02: 17: 00, нет совпадений

Не уверен, почему он печатает только записи из файлов1 и файлов2, когда есть совпадение.

Чтобы дать более подробную информацию об этом - я пытаюсь использовать эту команду awk для поиска различий в черно-белых файлах, а затем создать отчет, который в основном показывает, какие столбцы имеют разные значения.В идеале конечный результат будет выглядеть так:

id|Change| Columns  
1|No Change|NA  
2|Change|name  
3|Exists only in file 1|NA  
4|No Change|NA  
5|Change|description,name  
7|Exists only in file 2|NA 

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

Ответы [ 2 ]

0 голосов
/ 20 июня 2019

Читая ваш запрос, проще выполнить всю задачу, а не на промежуточном этапе.

Вот скрипт awk, который выполняет последнее задание.

script.awk

BEGIN {FS = OFS = "|"; f[2]="descr"; f[3] = "name"; f[4] = "date "}
FNR == NR {        # read first input file
    lines[$1] = $0;
    next;
}
{                  # read scond input file
    if ($1 in lines) { # index exist in file 1
        if ($0 == lines[$1]) { # compare indexed lines
            print $1, "Same", "NA";
        } else { # indexed lines differ
            split(lines[$1], file1Fields); # read all fields from file 1 line
            unmatchedFields = "";
            for (m = 2; m <= 4; m++) {
                if (file1Fields[m] != $m) { # compare each field
                    fieldsSeparator = length(unmatchedFields) ? "," : "";
                    unmatchedFields = unmatchedFields fieldsSeparator f[m];
                }
            }
            print $1, "change", unmatchedFields;
        }
        delete lines[$1]; # clean handled lines from file1
    } else { # index not seen in file 1, it is only in file 2
        print $1, "only in file 2", "NA";
    }
}
END {
    for (j in lines) {  # index only in file 1
        print j, "only in file 1", "NA";
    }
}

input.1.txt

id|description|name|date  
1|Row 1|a|2019-06-15 00:20:15:00  
2|Row 2|b|2019-06-16 15:18:10:00  
3|Row 3|c|2019-06-17 07:02:17:00  
4|Row 4|d|2019-06-25 09:00:01:00  
5|Row 5|e|2019-06-25 22:00:00:00  

input.2.txt

id|description|name|date  
1|Row 1|a|2019-06-15 00:20:15:00  
2|Row 2|c|2019-06-16 15:18:10:00  
4|Row 4|d|2019-06-25 09:00:01:00  
5|ROW 5|b|2019-06-25 22:00:00:00  
7|Row 7|f|2019-06-17 07:02:17:00 

работает:

awk -f script.awk input.1.txt input.2.txt |sort

выход:

1|Same|NA
2|change|name
3|only in file 1|NA
4|Same|NA
5|change|descr,name,date
7|only in file 2|NA
id|Same|NA
0 голосов
/ 20 июня 2019

С GNU awk для массивов массивов, gensub (), sorted_in и ARGIND:

$ cat tst.awk
BEGIN { FS=OFS="|" }
FNR==1 { next }
{ vals[$1][ARGIND] = gensub("^[^"FS"]+["FS"]","",1) }
END {
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (id in vals) {
        print id, \
           (1 in vals[id] ? vals[id][1] : "N/A"),
           (2 in vals[id] ? vals[id][2] : "N/A"),
           (vals[id][1] == vals[id][2] ? "" : "No ") "Match"
    }
}

$ awk -f tst.awk file1 file2
1|Row 1|a|2019-06-15 00:20:15:00|Row 1|a|2019-06-15 00:20:15:00|Match
2|Row 2|b|2019-06-16 15:18:10:00|Row 2|c|2019-06-16 15:18:10:00|No Match
3|Row 3|c|2019-06-17 07:02:17:00|N/A|No Match
4|Row 4|d|2019-06-25 09:00:01:00|Row 4|d|2019-06-25 09:00:01:00|Match
5|Row 5|e|2019-06-25 22:00:00:00|ROW 5|b|2019-06-25 22:00:00:00|No Match
7|N/A|Row 7|f|2019-06-17 07:02:17:00|No Match

или, если вы предпочитаете:

$ awk -f tst.awk file2 file1
1|Row 1|a|2019-06-15 00:20:15:00|Row 1|a|2019-06-15 00:20:15:00|Match
2|Row 2|c|2019-06-16 15:18:10:00|Row 2|b|2019-06-16 15:18:10:00|No Match
3|N/A|Row 3|c|2019-06-17 07:02:17:00|No Match
4|Row 4|d|2019-06-25 09:00:01:00|Row 4|d|2019-06-25 09:00:01:00|Match
5|ROW 5|b|2019-06-25 22:00:00:00|Row 5|e|2019-06-25 22:00:00:00|No Match
7|Row 7|f|2019-06-17 07:02:17:00|N/A|No Match

«N / A» поможет вам определить, какой из 2 файлов не имеет строки для данного идентификатора. Если вам это не нравится, тогда делайте массаж, который вам подойдет.


Обновление: вот как это сделать с любым awk и сортировкой:

$ cat tst.awk
BEGIN { FS=OFS="|" }
FNR==1 { argind++; next }
{
    id = $1
    ids[id]
    sub("^[^"FS"]+["FS"]","")
    vals[id,argind] = $0
}
END {
    for (id in ids) {
        print id, \
           ((id,1) in vals ? vals[id,1] : "N/A"),
           ((id,2) in vals ? vals[id,2] : "N/A"),
           (vals[id,1] == vals[id,2] ? "" : "No ") "Match"
    }
}

$ awk -f tst.awk file1 file2 | sort -t'|' -k1,1n
1|Row 1|a|2019-06-15 00:20:15:00|Row 1|a|2019-06-15 00:20:15:00|Match
2|Row 2|b|2019-06-16 15:18:10:00|Row 2|c|2019-06-16 15:18:10:00|No Match
3|Row 3|c|2019-06-17 07:02:17:00|N/A|No Match
4|Row 4|d|2019-06-25 09:00:01:00|Row 4|d|2019-06-25 09:00:01:00|Match
5|Row 5|e|2019-06-25 22:00:00:00|ROW 5|b|2019-06-25 22:00:00:00|No Match
7|N/A|Row 7|f|2019-06-17 07:02:17:00|No Match
...