什么是 NR 和 FNR,“NR==FNR”意味着什么?

Posted

技术标签:

【中文标题】什么是 NR 和 FNR,“NR==FNR”意味着什么?【英文标题】:What are NR and FNR and what does "NR==FNR" imply? 【发布时间】:2015-12-05 13:26:21 【问题描述】:

我正在学习使用awk进行文件比较。

我找到了如下语法,

awk 'NR==FNRa[$1];next$1 in aprint $1' file1 file2

我不明白NR==FNR在这有什么意义? 如果我尝试使用FNR==NR,那么我也会得到相同的输出吗?

它到底是做什么的?

【问题讨论】:

Two-file Processingbackreference.org/2010/02/10/idiomatic-awk 【参考方案1】:

在 awk 中,FNR 指的是当前文件中的记录号(通常是行号),NR 指的是总记录号。运算符==是一个比较运算符,当两个周围的操作数相等时返回true。

这意味着条件NR==FNR 仅适用于第一个文件,因为FNR 在每个文件的第一行重置回1,但NR 继续增加。

此模式通常用于仅对第一个文件执行操作。块内的next 表示跳过任何其他命令,因此它们仅在第一个以外的文件上运行。

条件FNR==NR 比较与NR==FNR 相同的两个操作数,因此其行为方式相同。

【讨论】:

"=" 有时用于测试相等性,有时用于进行分配。如果使用双等号进行分配,则 FNR==NR 将不同于 NR==FNR。所以对于不熟悉 awk 的人,比如这个提问者,问他们是否相同似乎是合理的。 @ToddWalton 好点!又如:a='3x'; if [[ $a == 3* ]]; then echo yes; fi== 两边不能切换。 @WalterA 是的,这是真的(至少在 Bash 中)。您是否建议对我的回答进行改进? 不,你的回答很好。我真的很想看到社区同样喜欢我们的答案。我们使用不同的风格,两者都被认为非常有帮助。我刚刚给了你一个赞成票,所以目前我们的赞成票数量相同。【参考方案2】:

在 file2 中查找也在 file1 中的键(行的第一个字)。 第 1 步:用文件 1 的第一个单词填充数组 a:

awk 'a[$1];' file1

第 2 步:在同一命令中填充数组 a 并忽略文件 2。为此,请使用当前输入文件的数量检查到目前为止的记录总数。

awk 'NR==FNRa[$1]' file1 file2

第 3 步:在解析文件 1 时忽略 之后可能发生的操作

awk 'NR==FNRa[$1];next' file1 file2 

第4步:在数组a中找到file2的键

awk 'NR==FNRa[$1];next $1 in aprint $1' file1 file2

【讨论】:

这个单行的精彩删除。第 1 步中的分号是必须的吗? @TomaszGandor 步骤 1 中不需要分号。我本可以在步骤 3 中添加它,但 ;next 是一个奇怪的添加(例如添加 next 并在步骤 3 中需要分号)。您可以使用awk 'a[$1] END for (k in a) print "a[k]=" k ' file1 测试第 1 步。【参考方案3】:

在awk手册中查找NRFNR,然后问自己以下示例中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

【讨论】:

是否也可以打印正在处理的文件的编号?有内置变量吗? (我知道我们可以为此创建一个变量,并在每次 NR 为 1 时递增它) 在 GNU awk 中,该变量为 ARGIND,否则您可以使用 FNR==1 print ++file_nr 我没有问任何问题,我展示了如何获得 OP 问题的答案。 这应该是“答案”。它清晰简洁,通过一个任何人都可以遵循的简单示例进行说明,并且不关心不精确的措辞。做得好! . 我将支持上述评论。这太棒了。【参考方案4】:

awk内置变量。

NR - 它给出了处理的记录总数。

FNR - 它给出每个输入文件的记录总数。

【讨论】:

【参考方案5】:

假设您有文件 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==FNRa[$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==FNRa[$0];nextif($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==FNRa[$0];nextif(!($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==FNRa[$0];next!($0 in a)' a.txt b.txt
2
6
7

【讨论】:

以上是关于什么是 NR 和 FNR,“NR==FNR”意味着什么?的主要内容,如果未能解决你的问题,请参考以下文章

awk中的NR FNR

awk打开多个文件的方法

awk常用命令

awk中 NR 和 NF到底是啥意思? 能举例说明吗?

awk实用语法

整理的几个好一点的awk案例