Что такое "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]
}
}