【问题标题】:How to merge two files based on one column and print both matching and non-matching?如何基于一列合并两个文件并打印匹配和不匹配?
【发布时间】:2019-08-09 13:28:29
【问题描述】:

我正在尝试合并两个文件,在 $1 上匹配它们,并将文件 2 中的匹配显示到新列 $3 中。如果它们不匹配,则该值应显示为 0。

例如我有以下两个文件

tmptest1.txt

aaa 231
bbb 132
ccc 111

tmptest2.txt

aaa 222
ddd 132

我希望输出文件是:

aaa 231 222
bbb 132 0
ccc 111 0
ddd 0 132

我尝试了下面的代码,虽然它确实将匹配的数字附加到 $3 中,但它忽略了不匹配的数字,因为我的打印语句只查看一个文件。我如何考虑两个文件的组合?

awk 'FNR==NR{a[$1]=$2;next} {print $1,$2,a[$1]}' tmptest1.txt tmptest2.txt | sort | awk '!$3{ $3="0"1}

结果

aaa 231 222
bbb 132 0
ccc 111 0

【问题讨论】:

    标签: unix awk


    【解决方案1】:

    假设您的真实文件按照您的样本排序:

    $ join -o 0,1.2,2.2 -e0 -a1 -a2 tmptest1.txt tmptest2.txt
    aaa 231 222
    bbb 132 0
    ccc 111 0
    ddd 0 132
    

    如果未排序并使用 bash、zsh、ksh93 或其他理解 <(command) 重定向的 shell:

    join -o 0,1.2,2.2 -e0 -a1 -a2 <(sort temptest1.txt) <(sort tmptest2.txt)
    

    【讨论】:

    • 谢谢!您介意向我简要介绍一下这些选项吗?
    【解决方案2】:

    多合一awk。这可行,但可能会缩短一些

    awk 'FNR==NR {a[$1]=$2;b[++j]=$1;next} 
        {if (a[$1]) 
            a[$1]=$1FS a[$1]FS$2; 
        else {
            a[$1]=$1FS"0"FS$2;b[++j]=$1}} 
    END {for (i=1;i<=j;i++) 
            if(a[b[i]]~/^[a-zA-Z]/)
                print a[b[i]];
            else print b[i],a[b[i]],"0"
        }
    ' tmptest1.txt tmptest2.txt
    aaa 231 222
    bbb 132 0
    ccc 111 0
    ddd 0 132
    

    【讨论】:

      猜你喜欢
      • 2018-07-12
      • 2017-08-19
      • 1970-01-01
      • 1970-01-01
      • 2012-09-05
      • 2016-10-23
      • 2021-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多