If you cant explain it simply, you dont understand it well enough

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 的效果是一样的,都是设置输入分隔符

 

posted @ 2014-08-29 21:34  zk47  阅读(2013)  评论(0编辑  收藏  举报

I am a stupid bird, and I need to work hard