zoukankan      html  css  js  c++  java
  • awk之NR==FNR,如何理解整理

    转载:https://www.cnblogs.com/irockcode/p/7044722.html

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

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

    下面看两个例子:

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 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,但是对于多个文件 :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 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的典型应用:

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

    1
    2
    3
    4
    5
    6
    7
    8
    #cat a
    张三|000001
    李四|000002
    #cat b
    000001|10
    000001|20
    000002|30
    000002|15

      

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

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

    执行如下代码

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

      

    注释:

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

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

    =========================================================================

    下面是CU大神jason680的详细过程分析

    awk -F'|' 'NR==FNR{a[$2]=$0;next}{print a[$1] FS $2}' a b

    There is no BEGIN block, and FS="|" by -F'|' argument
    没有开始模块,直接识别-F选项,加参数

    start to first file 'a' 
    从a文件的第一行开始
    1. read file a line 1 and get data 张三|000001
    读取文件a的第一行,得到数据
    A: $0=张三|000001
    B: $1=张三
    C: $2=000001

    NR and FNR are the same equal to 1, and run NR=FNR block
    此时,NR与FNR的值相等都为1,执行NR=FNR模块
    NR==FNR{a[$2]=$0;next}
    A: a[$2]=$0
    a[000001]=张三|000001
    B: next
    next cycle and get next line data 

    2. read file a line 2 and get data 李四|000002
    读取文件a的第二行,得到数据

    A: $0=李四|000002
    B: $1=李四
    C: $2=000002

    NR and FNR are the same equal to 2, and run NR=FNR block
    此时,NR与FNR的值相等都为2,执行NR=FNR模块
    NR==FNR{a[$2]=$0;next}
    A: a[$2]=$0
    a[000002]=李四|000002
    B: next
    next cycle and get next line data

    end of the file a, and get next file b data
    读完文件a,然后读取下一个文件b的数据

    3. read file b line 1, and get data 000001|10
    读取文件b的第一行,然后得到数据
    A: $0=000001|10
    B: $1=000001
    C: $2=10

    now, NR is 3 and FNR is 1, they are not eqaul
    此时,NR与FNR的值不同,不执行NF=FNR模块,执行下一个模块{print a[$1] FS $2}
    and didn't run NR=FNR block, 
    and run next block {print a[$1] FS $2} 
    a[$1] => a[000001] => 张三|000001
    FS => |
    $2 => 10
    you will see the output
    张三|000001|10

    4. read file b line 2, and get data 000001|20
    A: $0=000001|20
    B: $1=000001
    C: $2=20

    NR is 4 and FNR is 2, they are not eqaul
    and didn't run NR=FNR block, 
    and run next block {print a[$1] FS $2} 
    a[$1] => a[000001] => 张三|000001
    FS => |
    $2 => 20
    you will see the output
    张三|000001|20

    cycle to read the file b 
    5. read file b line 3, and get data 000002|30
    ...
    output==> 李四|000002|30

    6. read file b line 4, and get data 000002|15
    ...
    output==> 李四|000002|15

    补充:


    找出两个文件之间的不同部分

    awk 'NR==FNR{a[$0]++} NR>FNR&&!a[$0]' 1.txt 2.txt

    awk 'NR==FNR{a[$0]}NR>FNR{ if(!($1 in a)) print $0}' 1.txt 2.txt

    找出两个文件之间的相同部分

    awk 'NR==FNR{a[$0]++} NR>FNR&&a[$0]' 1.txt 2.txt

    awk 'NR==FNR{a[$0]}NR>FNR{ if($1 in a) print $0}' 1.txt 2.txt

  • 相关阅读:
    说说你对集成测试中自顶向下集成和自底向上集成两个策略的理解,要谈出它们各自的优缺点和主要适应于哪种类型测试;
    通过画因果图来写测试用例的步骤为___、___、___、___及把因果图转换为状态图共五个步骤。 利用因果图生成测试用例的基本步骤是:
    性能测试的流程?
    简述bug的生命周期?
    主键、外键的作用,索引的优点与不足?
    循序渐进VUE+Element 前端应用开发(30)--- ABP后端和Vue+Element前端结合的分页排序处理(转载)
    循序渐进VUE+Element 前端应用开发(31)--- 系统的日志管理,包括登录日志、接口访问日志、实体变化历史日志(转载)
    黑盒测试和白盒测试是软件测试的两种基本方法,请分别说明各自的优点和缺点!     
    如何测试一个纸杯?
    测试计划工作的目的是什么?测试计划文档的内容应该包括什么?其中哪些是最重要的?
  • 原文地址:https://www.cnblogs.com/helloworldPC/p/12668849.html
Copyright © 2011-2022 走看看