bash - 使用 awk 如何合并 2 个文件,比如 A 和 B 并执行左外连接功能并包含两个文件中的所有列

标签 bash awk

我有多个列数不同的文件,我需要对第一个文件和第二个文件进行合并,并在 awk 中分别对第一个文件进行左外连接,并打印两个文件中与两个文件的第一列匹配的所有列文件。

我尝试了以下代码来接近我的输出。但是我无法打印“,”,在第二个文件中找不到匹配的数字。下面是代码。加入需要排序并且比 awk 花费更多的时间。我的文件很大,大约有 3000 万条记录。

awk -F ',' '{  
    if (NR==FNR){ r[$1]=$0}
    else{ if($1 in r) 
    r[$1]=r[$1]gensub($1,"",1)}
}END{for(i in r){print r[i]}}' file1 file2

file1

number,column1,column2,..columnN

File2

numbr,column1,column2,..columnN

Output

number,file1.column1,file1.column2,..file1.columnN,file2.column1,file2.column3...,file2.columnN

file1

1,a,b,c
2,a,b,c
3,a,b,c
5,a,b,c

file2

1,x,y
2,x,y
5,x,y
6,x,y
7,x,y

desired output

1,a,b,c,x,y
2,a,b,c,x,y
3,a,b,c,,,
5,a,b,c,x,y

最佳答案

$ cat tst.awk
BEGIN { FS=OFS="," }
NR==FNR {
    tail = gensub(/[^,]*,/,"",1)
    if ( FNR == 1 ) {
        empty = gensub(/[^,]/,"","g",tail)
    }
    file2[$1] = tail
    next
}
{ print $0, ($1 in file2 ? file2[$1] : empty) }

$ awk -f tst.awk file2 file1
1,a,b,c,x,y
2,a,b,c,x,y
3,a,b,c,,
5,a,b,c,x,y

上面使用 GNU awk 来实现 gensub(),对于其他 awk,这只是在初始分配后对适当的变量执行 [g]sub() 的又一步。

您可能想要测试性能差异的一个有趣的(至少对我而言!)替代方案是:

$ cat tst.awk
BEGIN { FS=OFS="," }
NR==FNR {
    tail = gensub(/[^,]*,/,"",1)
    idx[$1] = NR
    file2[NR] = tail
    if ( FNR == 1 ) {
        file2[""] = gensub(/[^,]/,"","g",tail)
    }
    next
}
{ print $0, file2[idx[$1]] }

$ awk -f tst.awk file2 file1
1,a,b,c,x,y
2,a,b,c,x,y
3,a,b,c,,
5,a,b,c,x,y

但我真的不希望它更快,甚至可能更慢。

关于bash - 使用 awk 如何合并 2 个文件,比如 A 和 B 并执行左外连接功能并包含两个文件中的所有列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40905983/

相关文章:

awk 输出字段中文本的唯一计数

c - 根据列合并两个文件并排序

linux - 将文本文件重新格式化为一行字符串

bash 使用 xpath 解析 XHTML

linux - 如何将多行回显到来自 grep 结果的文件中

AWK 参数与文件

linux - 在 bash 中处理文本 - 从 pactl sink-inputs 输出中提取程序的体积

MySQL 无法检测 jq 生成的 CSV 中的换行符

javascript - 在我的 Flask 应用程序中嵌入 Bash shell?

linux - Bash,如果文件为空,如果不继续则离开脚本