AWK:根据文件中给出的重叠范围合并两个文件

AWK: merge two files based on the overlapping range given in the files

让我用一个虚拟的例子来解释我的问题。 这是文件 A -

1 10 20 aa
2 30 40 bb
3 60 70 cc
. .. .. ..

并且这是文件 B -

10 15 xx yy mm
21 29 mm nn ss
11 18 rr tt yy
69 90 qq ww ee
.. .. .. .. ..

我正在尝试合并这些文件 A 和 B,以便 A 的行和 B 的行之间存在一些重叠。

在我的例子中,A 行和 B 行重叠: A 的行从 2 美元到 3 美元的范围与 B 的行的 1 美元到 2 美元的范围之间有一些共同点。在上面的示例中,range(10,20) 和 range(10,15) 之间存在重叠。 这里范围(10,20)= [10,11,12,13,14,15,16,17,18,19] 和 范围(10,15)= [10,11,12,13,14]

所以预期的输出是-

1 10 20 aa 10 15 xx
1 10 20 aa 11 18 rr
3 60 70 cc 69 90 qq

我试过这种方式(使用 awk):

    for peak in State.peaks:
        i = peak[-1]
        peak = peak[:-1]
        a = peak[1]
        b = peak[2]
        d = State.delta
        c = ''' awk '{id=%d;delta=%d;a=%d;b=%d;x=%s;y=%s;if((x<=a&&y>a)||(x<=b&&y>b) || (x>a&&y<=b)) print id" "" "-} ' %s > %s ''' % (i, d, a, b, "-d", "+d", State.fourD, "file"+str(name))
        os.system(c)

想要完全删除 python 部分,因为它需要很多时间。

awk 救援!

$ awk 'function intersect(x1,y1,x2,y2) 
         {return (x1>=x2 && x1<y2) || (x2>=x1 && x2<y1)}

       NR==FNR{lower[[=10=]]=; upper[[=10=]]=; next}

              {for(k in lower) 
                 if(intersect(lower[k],upper[k],,)) 
                    print k,,,}' file1 file2

注意

(x1>=x2 && x1<y2) || (x2>=x1 && x2<y1) 
= [x1>=x2 || (x2>=x1 && x2<y1)]            && [x1<y2 || (x2>=x1 && x2<y1)]
= [(x1>=x2 || x2>=x1) && (x1>=x2 || x2<y1) && [// symmetric 1~2]
= [True               && x2 < max(x1,y1)]  && [// symmetric 1~2]  
= x2<y1 && y2<x1

这相当于@Jonathan Leffler 的条件,它更紧凑、更高效,尽管乍一看并不微不足道。

这个 Awk 脚本可以完成这项工作:

NR == FNR { record[NR] = [=10=]; lo[NR] = ; hi[NR] = ; nrecs = NR; next }
NR != FNR { # Overlap:  lo[A] < hi[B] && lo[B] < hi[A]
            for (i = 1; i <= nrecs; i++)
            {
                if (lo[i] <  &&  < hi[i])
                    print record[i], , , 
            }
          }

我将其保存为 range-merge-53.awk53 只是一个 运行dom double-digit 素数)。我根据您的示例数据创建了 file.Afile.B,并且 运行:

$ awk -f range-merge-53.awk file.A file.B
1 10 20 aa 10 15 xx
1 10 20 aa 11 18 rr
3 60 70 cc 69 90 qq
$

关键是 'overlap' 条件,它必须排除每个 运行ge 的高值 — 通常表示为 [lo..hi) open-closed 运行 ge.

可以省略 nextNR != FNR 条件(但不能同时省略),代码也可以正常工作。

另见 Determine whether two date ranges overlap — 运行ges 的逻辑适用于日期、整数和浮点等。