连接根据第二列按数字排序的两个文件

连接根据第二列按数字排序的两个文件

我有两个文件

文件 1 包含

2*J=0 EXP= 0.00000
2*J=4 EXP= 1.27911
2*J=8 EXP= 1.57613
2*J=12 EXP= 1.69134
2*J=10 EXP= 2.72705
2*J=16 EXP= 4.55689
2*J=20 EXP= 5.62138

文件 2 包含

2*J=0 EXC= 0.00000
2*J=8 EXC= 1.21836
2*J=4 EXC= 1.59642
2*J=12 EXC= 1.78359
2*J=10 EXC= 2.69484
2*J=16 EXC= 7.24518
2*J=20 EXC= 7.32688

我想加入这两个文件,以便输出为

2*J=0 EXP= 0.00000 EXC= 0.00000
2*J=4 EXP= 1.27911 EXC= 1.59642
2*J=8 EXP= 1.57613 EXC= 1.21836
2*J=12 EXP= 1.69134 EXC= 1.78359
2*J=10 EXP= 2.72705 EXC= 2.69484
2*J=16 EXP= 4.55689 EXC= 7.24518
2*J=20 EXP= 5.62138 EXC= 7.32688

答案1

使用 GNU awk,我们可以控制输出的排序方式:

加入者.awk

#!/usr/bin/env -S gawk -f

FILENAME == ARGV[1] {
    f1[$1] = $2 OFS $3
    sort_key[$1] = $3
    next
}

{
    f2[$1] = $2 OFS $3
}

function sorter(idx1, val1, idx2, val2) {
    return sort_key[idx1] - sort_key[idx2]
}

END {
    PROCINFO["sorted_in"] = "sorter"
    for (key in f1)
        print key, f1[key], f2[key]
}

然后

$ gawk -f joiner.awk file1 file2
2*J=0 EXP= 0.00000 EXC= 0.00000
2*J=4 EXP= 1.27911 EXC= 1.59642
2*J=8 EXP= 1.57613 EXC= 1.21836
2*J=12 EXP= 1.69134 EXC= 1.78359
2*J=10 EXP= 2.72705 EXC= 2.69484
2*J=16 EXP= 4.55689 EXC= 7.24518
2*J=20 EXP= 5.62138 EXC= 7.32688

“PROCINFO”魔法有记录:https://www.gnu.org/software/gawk/manual/html_node/Controlling-Array-Traversal.html

答案2

对于join,输入必须根据连接键按词法排序。如果您需要以其他方式对结果进行排序,则必须在加入后进行排序:

$ join <(sort -bk1,1 file1) <(sort -bk1,1 file2) | sort -k3n
2*J=0 EXP= 0.00000 EXC= 0.00000
2*J=4 EXP= 1.27911 EXC= 1.59642
2*J=8 EXP= 1.57613 EXC= 1.21836
2*J=12 EXP= 1.69134 EXC= 1.78359
2*J=10 EXP= 2.72705 EXC= 2.69484
2*J=16 EXP= 4.55689 EXC= 7.24518
2*J=20 EXP= 5.62138 EXC= 7.32688

sort -k3n对以第三个字段开头的行部分进行数字排序(默认情况下,字段通过从非空白到空白的转换来分隔,因此排序键包括前导空白和数字后面的内容,但在解释该字段时,两者都会被忽略作为数字;指定第三个空白分隔字段的更正确方法是sort -bk3,3n,其中-b删除空格并3,3选择仅有的第三个字段;实际上,这在功能上没有区别)。

进程替换 ( <(...)) 是 Korn shell 扩展。它也有zshbash外壳可供选择。

sort -bk1,1join在第一个空白分隔字段上按词法排序(默认情况下键连接)。

相关内容