• awk 处理多个文件


    awk 处理多个文件

    awk处理多个文件的方式是:一个一个的处理。

    Demo1

    $ cat 1.txt 
    a 1 
    b 2
    c 3
    d 4
    
    $ cat 2.txt 
    b 5 
    c 6
    d 7
    e 8
    
    $ awk '{print $0}' 1.txt 2.txt
    a 1 
    b 2
    c 3
    d 4
    b 5 
    c 6
    d 7
    e 8
    

    那怎么分辨当前处理的是哪一个文件呢?先看一下awk的内建变量有哪些。

    FILENAME: 当前输入的文件名字
    FNR: 当前输入文件的记录数
    NR: awk开始工作处理的总的记录数
    NF: 当前记录的字段数
    FS: 输入字段分割符
    OFS: 输出字段分隔符
    RS: 输入记录分隔符
    ORS: 输出记录分隔符
    ARGIND: 当前处理参数的标志,对于Demo1中的 1.txt 该值是1,2.txt是2
    ARGV: 命令行参数数组,对于Demo1是,ARGV[1]="1.txt" ARGV[2]="2.txt"
    ARGC: 命令行参数的个数

    对于两个文件的时候,我们可以这么处理:

    方法1 -- by FNR & NR
    由上可知,只有处理第一个文件的时候FNR才会等于NR,所以可以如下所示:

    $ awk 'FNR==NR{print $0}FNR!=NR{print $0}' 1.txt 2.txt 
    $ awk 'FNR==NR{print $0}FNR<NR{print $0}' 1.txt 2.txt
    

    方法2 -- by FILENAME

    $ awk 'FILENAME=="1.txt"{print "file1:"$1}FILENAME=="2.txt"{print "file2:" $2}' 1.txt 2.txt
    

    方法3 -- by FILENAME & ARGV
    方法2不是很灵活,因为下次换输入的时候,整个命令行都要改一下,很麻烦,其实可以通过ARGV来获取输入的变量名,awk把所有的输入变量都是存放在数组ARGV中。所以可以根据ARGV来获取输入的文件名,提高命令行的灵活性。

    $ awk 'FILENAME==ARGV[1]{print "file1:"$1}FILENAME==ARGV[2]{print "file2:" $2}' 1.txt 2.txt
    

    方法4 -- by ARGIND
    方法3貌似也有点复杂,可以通过ARGIND来实现。

    $ awk 'ARGIND==1{print "file1:"$1}ARGIND==2{print "file2:" $2}' 1.txt 2.txt
    

    上面四个的运行结果都是:

    file1:a 1 
    file1:b 2
    file1:c 3
    file1:d 4
    file2:b 5 
    file2:c 6
    file2:d 7
    file2:e 8
    

    对于处理两个以上文件的时候,方法1是不行的,可以用方法2,3,4来实现。

    应用举例:


    Demo2: 比较两个文件中第一列相同的行,并把文件1中相同的行print出。 对于Demo1中的文件1,文件2,最后输出:

    b 2
    c 3
    d 4
    

    实现方式:

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

    先将1.txt做一个字典映射,key是第一列,value是一行,然后取2.txt的第一列为key取字典中的value即可。

    Demo3: 借鉴一下别人的例子:比较 file1的1-4字符 和 file2的2-5 字符,如果相同,将file2 的第二列 与 file1 合并 file3(http://bbs.chinaunix.net/thread-577044-1-1.html

    $ cat file1
    0011AAA 200.00 20050321 
    0012BBB 300.00 20050621 
    0013DDD 400.00 20050622 
    0014FFF 500.00 20050401 
    
    $ cat file2
    I0011  11111 
    I0012  22222 
    I0014  55555 
    I0013  66666 
    
    $ awk 'NR==FNR{a[substr($1,1,4)]=$0}NR!=FNR&&a[b=substr($1,2,5)]{print a[b] $2}' file1 file2
    0011AAA 200.00 20050321 11111
    0012BBB 300.00 20050621 22222
    0014FFF 500.00 20050401 55555
    0013DDD 400.00 20050622 66666
    

    这里主要要注意&&a[b=substr($1,2,5)]这块,相当于是一个前置条件,即file2的2:5字符如果没有出现就不会执行后面的print语句。

    Demo4: 输入下面两个文件

    $ cat 1.txt 
    10/05766798607,11/20050325191329,29/0.1,14/05766798607 
    10/05767158557,11/20050325191329,29/0.08,14/05767158557 
    
    $ cat 2.txt 
    05766798607 
    05766798608 
    05766798609 
    

    输出:

    10/05766798607,11/20050325191329,29/0.1,14/05766798607 
    

    实现方法:

    $ awk -F'[/,]' 'NR==FNR{a[$0]=$0}FNR!=NR{if ($2 in a) print $0}' 2.txt 1.txt
    $ awk 'BEGIN{FS="[/,]"}NR==FNR{a[$0]}NR!=FNR{if ($2 in a) print $0}' 2.txt 1.txt 
    

    前后两个执行的结果是一样的,-FFS 的效果是一样的,都是设置输入分隔符

  • 相关阅读:
    [问题说明]文章中的Javascript造成首页无法正常显示
    目前博客园程序存在的性能问题
    日志文件分析工具—AWStats在IIS中的配置步骤
    [公告]博客园管理团队新增成员wayfarer
    mass Framework class模块 v6
    mass Framework ecma模块
    python 批量修改文件后缀
    创建纯空Object
    我的模块加载系统 v7
    软件公司的两种管理方式
  • 原文地址:https://www.cnblogs.com/zk47/p/3945774.html
Copyright © 2020-2023  润新知