使用AWK进行文件内容join
source link: https://blog.yourtion.com/join-file-data-using-awk.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
使用AWK进行文件内容join
最近在做一个项目,需要在两个不同的数据源上导出两个 CSV 文件,同时对导出的文件进行类似于 SQL 的 join 操作,由于只是一个查询脚本,没办法修改程序或者数据库等功能,所以就想到将 csv 文件导出后,通过 Linux 自带的命令来完成内容的合并。
首选的工具自然是最强大的 AWK 了。
AWK是一种优良的文本处理工具,Linux及Unix环境中现有的功能最强大的数据处理引擎之一。 https://zh.wikipedia.org/zh-hans/AWK
首先来看一导出的两个 csv 文件:
channel.csv 主要保存渠道 ID 与渠道名称的关系
id Name
1 渠道1
2 渠道2
...
data.csv 记录每个渠道带来的 PV/UV 等信息
id pv uv submit
2 4 3 2
12 1 1 0
3 1 1 0
...
需要的结果是将两个文档进行整合,输出一个完整的csv
channle id pv uv submit
渠道2 2 4 3 2
未知 12 1 1 0
渠道3 3 1 1 0
其实解答的一个思路还是比较简单的,因为渠道 ID 本身不会重复,最简单的方法就是将其转换为一个字典,然后对于 data.csv 的内容根据 id 去字典中获取对应的渠道名称,最后组合到一起。
首先去网上找到了一个在 awk 内按行读取文件的方法,并根据需求将文件内容转换成一个数组(其实 awk 里面数组跟 map 是一样的)。最后再按行拼装数据即可。
需要处理一下渠道 ID 找不到对应的情况,很简单,同一个三元表达式即可 $1 in File ? File[$1] : "未知"
。
首先是最核心的 join.awk ,实现了 awk 核心的逻辑:
function read_file_into_array(file, array, status, record) {
while (1) {
status = getline record < file
if (status == -1) {
print "Failed to read file " file;
exit 1;
}
if (status == 0) break;
split(record, a, "\t");
array[a[1]] = a[2];
}
close(file);
}
BEGIN {
read_file_into_array(CHANNEL, File);
}
{
if(NR == 1) {
print "channel\tid\tpv\tuv\tsubmit"
next
}
{ printf("%s\t%s\t%s\t%s\t%s\t\n", ($1 in File ? File[$1] : "未知"),$1,$2,$3,$4) }
}
执行方法(通过 CHANNEL 参数传入变量):
$ awk -v CHANNEL=channel.csv -f join.awk data.csv
运行结果:
代码详见:https://github.com/yourtion/BlogCodes/tree/master/awk_join
- https://www.unix.com/302417048-post3.html
- https://www.unix.com/303007698-post1.html
- https://blog.csdn.net/bitcarmanlee/article/details/51324585
原文链接:https://blog.yourtion.com/join-file-data-using-awk.html
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK