加入:两个文件 - 但只附加最后两列

Ste*_*Kin 5 sed awk files merge join

鉴于文件:

1.txt

1, abc, 123, 456, 789
2, lmn, 123, 456, 789
3, pqr, 123, 456, 789
Run Code Online (Sandbox Code Playgroud)

2.txt

1, abc, 123, 000, 000
3, lmn, 123, 000, 000
9, opq, 123, 000, 000  
Run Code Online (Sandbox Code Playgroud)

输出.txt

ID, NAME, X,    1A,    1B,  2A,   2B   
1, abc, 123, 456, 789, 000, 000
2, lmn, 123, 456, 789, MISSING, MISSING
3, pqr, 123, 456, 789, 000, 000
9, opq, 123, MISSING, MISSING, 000, 000 
Run Code Online (Sandbox Code Playgroud)

我用过这个作为参考。

我尝试使用以下方法:

join -t , -a1 -a2 -1 1 -2 1 -o 0 -o 1.2 -o 1.3 -o 1.4 -o 1.5 -o 2.4 -o 2.5 -e "MISSING" 1.txt 2.txt
Run Code Online (Sandbox Code Playgroud)

其中产生:

1, abc, 123, 456, 789, 000, 000
2, lmn, 123, 456, 789,MISSING,MISSING
3, pqr, 123, 456, 789, 000, 000
9,MISSING,MISSING,MISSING,MISSING, 000, 000
Run Code Online (Sandbox Code Playgroud)

有什么帮助吗?

Sté*_*las 8

我不认为你一个人可以做到join。你可以这样做:

join -t, -a1 -a2 -o0,1.2,1.3,1.4,1.5,2.2,2.3,2.4,2.5 -e MISSING 1.txt 2.txt |
  perl -F, -lape '@F[1..2]=@F[5..6] if $F[1] eq "MISSING";
                  $_=join",",@F[0..4],@F[7..8]'
Run Code Online (Sandbox Code Playgroud)
  • -p: 像在 sed/awk 中一样使用逐行读取循环
  • -a, -F,: 和 awk 一样,将行拆分为字段(到@F数组中)。
  • -l: 处理行的内容(就像awk输入在RS( $/)上拆分(但RS不包括在$0)和ORS( $\) 在打印之前附加的地方)。
  • -e ...: perl [e]xpression 对每一行进行评估。
  • 然后它读起来几乎像英语:如果字段 1(作为索引的第二个字段从 0 开始)是“MISSING”,则字段 1 到 2 被设置为字段 5 到 6。然后将当前记录的内容($_就像awk中的$0)设置为字段0到4和7到8。

实际上,将相同的awk内容写入并没有更复杂:

awk -F, -vOFS=, '$2 == "MISSING"{$2=$6;$3=$7}
                 {print $1,$2,$3,$4,$5,$8,$9}'
Run Code Online (Sandbox Code Playgroud)


gle*_*man 5

只使用 awk:

awk -F, -v OFS=, '
    BEGIN {m = " MISSING"}

    # process file1
    NR == FNR {lines[$1] = $0; next} 

    # process file2
    {
        added[$1] = $4 OFS $5
        if (!($1 in lines)) {
            $4 = m
            $5 = m
            lines[$1] = $0
        }
    } 

    # print the combined output
    END {
        for (id in lines) {
            if (!(id in added)) 
                added[id] = m OFS m
            print lines[id], added[id]
        }
    }
' 1.txt 2.txt | sort -n
Run Code Online (Sandbox Code Playgroud)
1, abc, 123, 456, 789, 000, 000
2, lmn, 123, 456, 789, MISSING, MISSING
3, pqr, 123, 456, 789, 000, 000
9, opq, 123, MISSING, MISSING, 000, 000  
Run Code Online (Sandbox Code Playgroud)