awk 之 in NR FNR 用法实例

转载自:http://blog.chinaunix.net/uid-10540984-id-323936.html

 

awk之in的运用实例 2011-05-18 15:44:47

分类: LINUX

这个特殊的for循环用于对数组的迭代
for ( a in b ) {...}
这段代码将打印数组 b 中的每一个元素 ,当对于 for 使用这种特殊的 "in" 形式时
awk 将 数组b的每个现有下标依次赋值给 a(循环控制变量),每次赋值以后都循环一次循环代码。他的缺点是 它不会依照任何特定的顺序。

 

 

  1. $ cat a
  2. 1 a
  3. 2 f
  4. 3 5
  5. 4 8
  6. $ cat b
  7. 1 a
  8. 2 f
  9. 3 5
  10. 5 8

有这么两个文本,要求以文本a的第一个字段为比较,如果文本b的第一个字段与a不符合,那么打印出该行。

 

  1. awk 'NR==FNR{a[$1];next}!($1in a)' a b
  2. 5 8

[解析]

  首先NR==FNR对文本a进行处理,把$1的值作为下标放入数组a,next不会执行后面的语句,一直读到文本b不满足NR==FNR条件,这时判断文本b的$1是否存在于数组a中的下标中,显然文本b的第一行的$1是存在于数组a的下标中的,那么条件为真,再!,注意非真即为假,为假那么不会执行该pattern后面默认的{print]这个action动作,那么则不会输出该行,一直到第4行的$1并未存在于数组a的下标中,那么条件为假,非假为真,则执行默认的打印,输出了该行。或许下面的写法更符合规范和便于理解:

  1. awk 'NR==FNR{a[$1];next}{if(!($1in a))print $0}' a b

 

    还有没有更简单的方法呢?有的,呵呵,利用pattern的特性,我写出了下面的语句,更短:

  1. awk 'NR==FNR{a[$1]=1;next}!a[$1]' a b

[解析]

  给该数组赋予一个值为1,如果文本b的$1存在数组a中,那么数组a的值则为1,非真为假,则不输出,如果不存在数字a中,那么数组a的值是为0的,非假为真,则打印。

 

书上说:

NR,表示awk开始执行程序后所读取的数据行数.

FNR,与NR功用类似,不同的是awk每打开一个新文件,FNR便从0重新累计.

下面看两个例子:

1,对于单个文件NR 和FNR 的 输出结果一样的 :

# awk '{print NR,$0}' file1
1 a b c d
2 a b d c
3 a c b d

#awk '{print FNR,$0}' file1
1 a b c d
2 a b d c
3 a c b d

2,但是对于多个文件 :

# awk '{print NR,$0}' file1 file2
1 a b c d
2 a b d c
3 a c b d
4 aa bb cc dd
5 aa bb dd cc
6 aa cc bb dd

# awk '{print FNR,$0}' file1 file2
1 a b c d
2 a b d c
3 a c b d
1 aa bb cc dd
2 aa bb dd cc
3 aa cc bb dd

在看一个例子关于NR和FNR的典型应用:

现在有两个文件格式如下:

#cat account
张三|000001
李四|000002
#cat cdr
000001|10
000001|20
000002|30
000002|15

想要得到的结果是将用户名,帐号和金额在同一行打印出来,如下:

张三|000001|10
张三|000001|20
李四|000002|30
李四|000002|15

执行如下代码

#awk -F \| 'NR==FNR{a[$2]=$0;next}{print a[$1]"|"$2}' account cdr

注释:

由NR=FNR为真时,判断当前读入的是第一个文件account,然后使用{a[$2]=$0;next}循环将account文件的每行记录都存入数组a,并使用$2第2个字段作为下标引用.

由NR=FNR为假时,判断当前读入了第二个文件cdr,然后跳过{a[$2]=$0;next},对第二个文件cdr的每一行都无条件执行{print a[$1]"|"$2},此时变量$1为第二个文件的第一个字段,与读入第一个文件时,采用第一个文件第二个字段$2为数组下标相同.因此可以在此使用a[$1]引用数组。

本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2012-05/61174.htm

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值