Как проверить, существует ли строка из текстового файла в другом текстовом файле с помощью awk

Это дополнительный вопрос из: Неожиданный результат при сравнении значений строк и столбцов в двух текстовых файлах

Я создал структуру для сравнения двух текстовых файлов по их строкам и столбцам. Вот файловые структуры:

файл1.txt

Name  Col1  Col2  Col3 
-----------------------
row1  1     4     7         
row2  2     5     8          
row3  3     6     9

файл2.txt

Name  Col1  Col2  Col3   
-----------------------         
row1  1     4     7 
row2  2     5     999

Вот код, который у меня есть до сих пор:

dos2unix ravi   # 2>/dev/null
dos2unix ravi2  # 2>/dev/null

awk '     
    FNR < 2 {next}       # skips first two lines
    FNR == NR {           
        for (i = 2; i <= NF; i++) {
            a[i,$1] = $i;               
        }    
        b[$1];               
        next;                       
    }

    ($1 in b) {                   # check if row in file2 existed in file1
        for (i = 2; i <= NF; i++) {
            if (a[i,$1] == $i) 
                printf("%s->col%d: %s vs %s: Are Equal\n", $1, i-1, a[i,$1], $i);
            else 
                printf("%s->col%d: %s vs %s: Not Equal\n", $1, i-1, a[i,$1], $i);
        }
    }

    !($1 in b) {                  # check if row in file2 doesn't exist in file1. 
        for (i = 2; i <= NF; i++) 
            printf("%s->col%d: %s vs %s: Are Not Equal\n", $1, i-1, "blank", $i);
    }

    // pattern needed to check if row in file1 doesn't exist in file2. 

    ' $PWD/file1.txt $PWD/file2.txt

Есть ли у кого-нибудь какие-либо советы, предложения или подсказки, чтобы иметь шаблон в операторе awk, чтобы проверить, не существует ли строка в файле 1 в файле 2. Посмотрите примеры выходных данных ниже, чтобы понять, что я имею в виду. (т.е.: в принципе, я хочу напечатать значения строки 3 в файле 1, которые не существуют в файле 2). Спасибо! Дайте мне знать, если необходимы дополнительные объяснения.

Желаемый результат:

row2->Col1: 1 vs 1: Equal
row2->Col2: 4 vs 4: Equal
row2->Col3: 7 vs 7: Equal
row1->Col1: 2 vs 2: Equal
row1->Col2: 5 vs 5: Equal
row1->Col3: 8 vs 999: Not Equal
row3->Col1: 3 vs (blank) : Not Equal
row3->Col2: 6 vs (blank) : Not Equal
row3->Col3: 9 vs (blank) : Not Equal

Фактический результат:

row2->Col1: 1 vs 1: Equal
row2->Col2: 4 vs 4: Equal
row2->Col3: 7 vs 7: Equal
row1->Col1: 2 vs 2: Equal
row1->Col2: 5 vs 5: Equal
row1->Col3: 8 vs 999: Not Equal

person Redson    schedule 20.06.2014    source источник
comment
Вероятно, вам следует использовать для этого небольшой скрипт на Python, но это всего лишь мои два цента.   -  person Florin Stingaciu    schedule 20.06.2014


Ответы (2)


Расширение вашего ответа:

$ cat script.awk 
FNR < 2 { next }       # skips first two lines
FNR == NR {
    for (i = 2; i <= NF; i++) { a[i,$1] = $i }
    b[$1];
    next;
}
($1 in b) {                   # check if row in file2 existed in file1
    for (i = 2; i <= NF; i++) {
        if (a[i,$1] == $i)
            printf("%s->col%d: %s vs %s: Are Equal\n", $1, i-1, a[i,$1], $i);
        else
            printf("%s->col%d: %s vs %s: Not Equal\n", $1, i-1, a[i,$1], $i);
    }
    delete b[$1];   # delete entries which are processed
}

END {
    for (left in b) {   # look which didn't match
        for (i = 2; i <= NF; i++) 
            printf("%s->col%d: %s vs (blank): Not Equal\n", left, i-1, a[i,left])
    }
}

Запустите его как:

$ awk -f script.awk file1 file2
row1->col1: 1 vs 1: Are Equal
row1->col2: 4 vs 4: Are Equal
row1->col3: 7 vs 7: Are Equal
row2->col1: 2 vs 2: Are Equal
row2->col2: 5 vs 5: Are Equal
row2->col3: 8 vs 999: Not Equal
row3->col1: 3 vs (blank): Not Equal
row3->col2: 6 vs (blank): Not Equal
row3->col3: 9 vs (blank): Not Equal
person jaypal singh    schedule 20.06.2014
comment
@jaypal Я ценю время, которое вы потратили на это кодирование (так что +1), но оно все еще не печатает row3 ни для одного столбца. - person Redson; 20.06.2014
comment
@Nosscire Убедитесь, что в них нет управляющих символов. Я только что проверил это, и он отлично работает с вашими данными. - person jaypal singh; 20.06.2014

Если вы знаете, что каждое имя строки (первый столбец) будет появляться в каждом файле не более одного раза, вы можете delete b[$1] в конце блока ($1 in b) переместить блок !($1 in b) над ним, а затем добавить блок END, который зацикливается на всем осталось в b и распечатывает ваши строки.

END {
    for (r in b) {
        for (i = 2; i <= NF; i++) {
            printf("%s->col%d: %s vs %s: Are Not Equal\n", r, i-1, $i, "blank");
        }
    }
}
person Etan Reisner    schedule 20.06.2014