Что такое "NR==FNR" в awk?

Я изучаю сравнение файлов, используя awk,

Я нашел синтаксис, как показано ниже,

awk 'NR==FNR{a[$1];next}$1 in a{print $1}' file1 file2

Я не мог понять, в чем смысл NR==FNR в этом? Если я попробую с FNR==NR тогда и я получаю такой же вывод?

Что именно это делает?

6 ответов

В awk, FNR относится к номеру записи (обычно это номер строки) в текущем файле и NR относится к общему количеству записей. Это означает, что условие NR==FNR верно только для первого файла, так как FNR сбрасывает обратно на 1 для первой строки каждого файла, но NR продолжает расти.

Этот шаблон обычно используется для выполнения действий только с первым файлом. next внутри блока означает, что любые дальнейшие команды пропускаются, поэтому они запускаются только для файлов, отличных от первой.

Непонятно, почему вы ожидаете FNR==NR отличаться от NR==FNR,

Ищите ключи (первое слово строки) в file2, которые также есть в file1.
Шаг 1: заполните массив a первыми словами файла 1:

awk '{a[$1];}' file1

Шаг 2: Заполните массив a и проигнорируйте файл 2 в той же команде. Для этого проверьте общее количество записей до сих пор с номером текущего входного файла.

awk 'NR==FNR{a[$1]}' file1 file2

Шаг 3: Игнорировать действия, которые могут произойти после } при разборе файла 1

awk 'NR==FNR{a[$1];next}' file1 file2 

Шаг 4: распечатать ключ файла 2, когда он найден в массиве

awk 'NR==FNR{a[$1];next} $1 in a{print $1}' file1 file2

Уважать NR а также FNR в руководстве по awk, а затем спросите себя, при каких условиях NR==FNR в следующем примере:

$ cat file1
a
b
c

$ cat file2
d
e

$ awk '{print FILENAME, NR, FNR, $0}' file1 file2
file1 1 1 a
file1 2 2 b
file1 3 3 c
file2 4 1 d
file2 5 2 e

Есть awk встроенные переменные.

NR - Это дает общее количество обработанных записей.

FNR - Он дает общее количество записей для каждого входного файла.

Предполагая, что у вас есть файлы a.txt и b.txt с

cat a.txt
a
b
c
d
1
3
5
cat b.txt
a
1
2
6
7

Имейте в виду, что NR и FNR являются встроенными переменными awk. NR - дает общее количество обработанных записей. (в этом случае как в a.txt, так и в b.txt) FNR - выдает общее количество записей для каждого входного файла (записей в a.txt или b.txt).

awk 'NR==FNR{a[$0];}{if($0 in a)print FILENAME " " NR " " FNR " " $0}' a.txt b.txt
a.txt 1 1 a
a.txt 2 2 b
a.txt 3 3 c
a.txt 4 4 d
a.txt 5 5 1
a.txt 6 6 3
a.txt 7 7 5
b.txt 8 1 a
b.txt 9 2 1

позволяет добавить "следующий", чтобы пропустить первое совпадение с NR==FNR

в b.txt и в a.txt

awk 'NR==FNR{a[$0];next}{if($0 in a)print FILENAME " " NR " " FNR " " $0}' a.txt b.txt
b.txt 8 1 a
b.txt 9 2 1

в b.txt, но не в a.txt

 awk 'NR==FNR{a[$0];next}{if(!($0 in a))print FILENAME " " NR " " FNR " " $0}' a.txt b.txt
b.txt 10 3 2
b.txt 11 4 6
b.txt 12 5 7

awk 'NR==FNR{a[$0];next}!($0 in a)' a.txt b.txt
2
6
7

Вот псевдокод для вашего интереса.

      NR = 1
for (i=1; i<=files.length; ++i) {
    line = read line from files[i]
    FNR = 1
    while (not EOF) {
        columns = getColumns(line)

        if (NR is equals to FNR) { // processing first file
            add columns[1] to a
        } else { // processing remaining files
            if (columns[1] exists in a) {
                print columns[1]
            }
        }
        NR = NR + 1
        FNR = FNR + 1
        line = read line from files[i]
    }
}
Другие вопросы по тегам