【Linux Shell脚本攻略之二】awk入门:join两个文件

      提一个简单的需求,求两个文件的join集合。具体举个例子:

file1:

1 sh wahaha
2 bj lebaishi
3 nj jack
4 sz rose
5 bj hahaha

file2:

bj 010
sh 021

过滤出file1的第二列的值与file2的第一列的值对应的相等的记录,用awk怎么实现?在这个问题的驱动之下,来整理一下awk。

一、awk工具简介

      一个awk由三个部分组成:BEGIN语句块、END语句块和能够使用模式匹配的通用语句块。这三个部分是可选的,任何一个部分都可以不出现在脚本中。

语法为:

awk 'BEGIN {statements} {statements} END {end statements}'

例如:

awk 'BEGIN {i = 0} {i++} END {print i}' filename

上面这句话可以理解成打印filename的行数。当然,打印filename的行号还有很多方式,比如下面两句:

awk 'END{print NR}' filename
wc -l filename | awk '{print $1}'

二、awk工作原理

     awk命令的工作方式如下:

(1)执行BEGIN{ commands }语句块中的语句

(2)从文件或stdin中读取一行,然后执行pattern{ commands }。重复这个过程,知道文件全部被读取完毕。

(3)当读至输入流(input stream)末尾时,执行END{ commands }语句块。

      BEGIN语句块在awk开始从输入流中读取行之前被执行。这是一个可选的语句块,诸如变量初始化、打印输出表格的表头等语句通常都可以写入BEGIN语句块中。

      END语句块和BEGIN语句块类似。END语句块awk从输入流中读取完所有的行之后即被执行。像打印所有行的分析结果这类汇总信息,都是在END语句块中实现的常见任务(例如,在比价过所有的行之后,打印出最大数)。它也是一个可选的语句块。

      最重要的部分是pattern语句块中的通用命令。这个语句块同样是可选的。如果不提供该语句块,则默认执行{print},即打印读一个读取到的行。这就像是一个用来读取行的while循环,在循环体中提供了相应的语句。

      每读取一行时,它就会检查该行和提供的样式是否匹配。样式本身可以是正则表达式、条件以及行匹配范围等。如果当前行匹配该样式,则执行{}中的语句。

三、awk常用参数

   下面解释一下awk的常用参数:

·NR:整个脚本当前已经读取过的记录数,就是行号,从1开始。随着所读文件的数目,一直累加。

·FNR:同NR,不过是针对当前在读的文件记录数。每开始读一个新文件时,从1开始累加,相当于行号。读完一个文件后就会清0,新的文件又会从1开始。

·FILENAME:当前文件名

·$0:读取文件的当前行

·$n(n>0):第n列数据

·NR:一行记录的字段的数目,也就是列数。

四、具体实现

     那么现在就说一下开头的那个需求怎么实现,先直接看看怎么写:

awk 'NR==FNR{a[$1]=$2;}NR!=FNR && a[$2] {print $0}' file2 file1

执行结果:

1 sh wahaha
2 bj lebaishi
5 bj hahaha

来解释一下:

      首先处理file2中的数据,由于是第一个文件,那么NR==FNR是满足条件的,那么就会生成数组a(举例:a['sh']='021'),然后执行NR!=FNR,结果不满足条件,不向后处理,直到循环到处理file1文件。此时前半段不满足条件,但是后半段满足条件,而同时对于file1中的第二列在数组a中出现过,即a[$2]不为空,那么就执行打印file1中每一行的数据。

当然处理两个文件的时候有多种方式:

awk 'NR==FNR{ block_one; next} { block_two }' file1 file2
awk 'NR==FNR{ block_one } NR>FNR{ block_two }' file1 file2
awk 'NR==FNR{ block_one } NR!=FNR{ block_two }' file1 file2

Author:忆之独秀

Email:[email protected]

注明出处:https://blog.csdn.net/lavorange/article/details/80410290


猜你喜欢

转载自blog.csdn.net/lavorange/article/details/80410290