linux - awk 要求合并两个文件

标签 linux bash awk sed

我通过 AWK 命令使用相同的 key 组合了两个不同的文件。 如果与 File1 和 File2 相比没有关键匹配,则只需 将“\t\t\t”改为“\t\t\t”。

我有以下 AWK 命令。

awk -F"\t" '
{key = $1}
NR == 1 {header = key}
!(key in result) {result[key] = $0 ; next}
{ for (i=2; i <= NF; i++) result[key] = result[key] FS $i }
END {
    print result[header],"\tValue2","\tValue3","\tValue4"
    delete result[header]
    PROCINFO["sorted_in"] = "@ind_str_asc"    # if using GNU awk
    for (key in result) print result[key]
}
' $1 $2 > $3

合并示例 文件1

Key    Value1
 A     10000
 B     20000
 C     30000
 D     40000

文件2

 B     50000      20000     10000   
 C     20000      10000     50000   

然后是预期结果

Key    Value1    Value2    Value3    Value4
 A     10000       -         -         -
 B     20000     50000     20000     10000   
 C     30000     20000     10000    50000   
 D     40000       -         -         -

我的 AWK 命令显示

Key    Value1    Value2    Value3    Value4
 A     10000       
 B     20000     50000     20000     10000   
 C     30000     20000     10000    50000   
 D     40000       

我已经尝试过像下面这样的一些方法

!(key in result) {result[key] = $0"\t-\t-\t-" ; next}

但看起来这并不能涵盖所有情况。 有人有更好的主意吗? 谢谢!

最佳答案

此解决方案不会硬编码 File2 中有 3 个额外字段

awk '
    BEGIN { FS = OVS = "\t" }
    NR == FNR {
        key = $1
        $1 = ""
        store[key] = $0
        num_extra_fields = NF-1
        next
    } 
    FNR == 1 {
        printf "%s", $0
        for (i=1; i <= num_extra_fields; i++) 
            printf "%sValue%d", OFS, i+(NF-1)
        print ""
        next
    } 
    $1 in store {
        print $0  store[key]
        next
    } 
    { 
        for (i=1; i <= num_extra_fields; i++) 
            $(++NF)="-"
        print
    }
' file2 file1 

由于 stackoverflow 显示选项卡的方式,输出看起来有点奇怪

Key Value1  Value2  Value3  Value4
A   10000   -   -   -
B   20000   20000   10000   50000
C   30000   20000   10000   50000
D   40000   -   -   -

要修复代码,您需要跟踪 file2 中更新结果的键。改变

{ for (i=2; i <= NF; i++) result[key] = result[key] FS $i }

{ updated[key]=1; for (i=2; i <= NF; i++) result[key] = result[key] FS $i }

并在 END block 中进行更改

  for (key in result) print result[key]

  for (key in result) {
    if (!(key in updated)) result[key] = result[key] FS "-" FS "-" FS "-"
    print result[key]
  }

关于linux - awk 要求合并两个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29476542/

相关文章:

linux - 禁用 linux 用户身份验证,除了通过 ldap

linux - Shell 命令中不需要的换行符(来自 VIM)

macos - 安装git时Git Bash找不到git目录

regex - awk regex 最后一次出现的字符/模式

regex - 根据特定列删除重复项

regex - AWK代码解析器,区分除法和正则表达式

linux - 更改搜索目录时文件的权限

linux - 获取与 shell 中的 sed 命令匹配的精确两行之间的行

linux - 如何使用通配符 grep 查找匹配的单词,而不是周围的行?

java - 为参数化变量创建 shell 脚本