awk实现类sql的join操作

网友投稿 235 2022-09-20

awk实现类sql的join操作

awk、grep和sed被称为linux三剑客,事实上grep和awk我在日常工作中也常用到(sed用的比较少),可能有些人对awk了解比较少,我先大概介绍下。 很多人以为awk只是一个文本处理工具,实际上他们也是这么用的。但事实上它其实是一门语言,拥有数学运算符、进程控制语句,甚至针对于文本处理封装了很多内置变量和函数,这造就了它强大的文本处理能力。 如果grep只能做到数据的筛选,那awk还能做到数据的处理、分析甚至生成报表,毕竟它是一门完整的编程语言。

因为这篇文章不是awk的入门教程,如果想入门的话我推荐阮一峰老师的​​awk 入门教程​​​ 和 左耳朵耗子的​​AWK 简明教程​​ 。

回到我今天的正题,今天我给大家看个我常使用awk的场景。因为做后端开发,经常在做数据分析的时候会有这样的问题,1.面对几十万条的数据,需要筛选出几百几千个特定key的数据。2.对这几百万条数据,针对其中的id字段补齐其他字段。

这时候可能有精通excel的同学跳出来说 “就这,so easy,vlookup就搞定!” ,事实上,excel确实可以解决问题,但有点重,甚至有些时候我们在服务器上还用不了excel。还有啥其他方法?针对我说的这俩场景,其实仔细想一下,是不是sql中俩表join就能解决问题。实际上你并不需要真正把文件灌到数据库里,只需要用awk一条命令就能解决。

实例

我们把问题具像下,假设有两个文件,score.txt存着学号+成绩的数据,另外一个name.txt存着学号+姓名的数据,你现在想知道每个人都烤了多少分。

score.txt

id score 1 872 673 684 755 906 1007 0

name.txt

id name 1 张三2 李四3 王五4 赵二5 刘能6 熊大

你想得到一份包含学号 姓名和成绩的数据,就像下面这样。

id score name 1 87 张三2 67 李四3 68 王五4 75 赵二5 90 刘能6 100 熊大7 0

用awk生成这样的数据有多简单?只需要一行代码,你可以保存name.txt和score.txt,然后执行下面命令尝试下。

awk 'ARGV[1]==FILENAME {map[$1]=$2} ARGV[2]==FILENAME {print $0, map[$1]}'

简简单单就实现了name.txt和score.txt在id之上的right join。

解释下上面的代码,ARGV和FILENAME是awk内置的变量,ARGV里存放在awk所接受的参数列表,像上面 ARGV[1]就是"name.txt",ARGV[2]就是"score.txt"。awk是面向行的,所以针对每一行数据都会执行​​ARGV[1]==FILENAME {map[$1]=$2} ARGV[2]==FILENAME {print $0, map[$1]}​​,每一行数据都会属于某个文件,FILENAME标识出当前行所属的文件名,像在括号​​{}​​​前的​​ARGV[1]==FILENAME​​ 你可以看做是其他语法中的条件判断,你可以认为它就是省略了if,但和if的功能是一致的。

结语

awk 'ARGV[1]==FILENAME {map[$1]=$2} ARGV[2]==FILENAME {print $0, map[$1]}'

针对于不同的数据,只需要调整下$后面的具体值,可以实现用不同的列作为key来做join,其实这里并不比sql的join复杂,但在linux服务器上却很方便。上网中我只是实现了right join,如果在​​print $0, map[$1]​​​前加上​​if (length(map[$1]) > 0)​​ 就可以实现inner join。left join的话也只需要把文件名换一下。

知道了这些,awk实现多文件的交集、差集等操作都不在话下。另外不要忘记了awk其实也是一门编程语言,所以它也可以实现很多很复杂的逻辑,你可以把代码在某个文件里然后用-f参数调起,比如我之前老师用awk做一些简单的统计工作,比如计算均值、总和…… awk简直堪称后端工程师提效利器。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:电脑时间倒流,程序拒绝穿越:应用程序发生异常 未知的软件异常(0xe06d7363)
下一篇:用户底层12.5亿!微信视频号最大流量蓝海?
相关文章

 发表评论

暂时没有评论,来抢沙发吧~