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.awk
(53
只是一个 运行dom double-digit 素数)。我根据您的示例数据创建了 file.A
和 file.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.
可以省略 next
或 NR != FNR
条件(但不能同时省略),代码也可以正常工作。
另见 Determine whether two date ranges overlap — 运行ges 的逻辑适用于日期、整数和浮点等。
让我用一个虚拟的例子来解释我的问题。 这是文件 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.awk
(53
只是一个 运行dom double-digit 素数)。我根据您的示例数据创建了 file.A
和 file.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.
可以省略 next
或 NR != FNR
条件(但不能同时省略),代码也可以正常工作。
另见 Determine whether two date ranges overlap — 运行ges 的逻辑适用于日期、整数和浮点等。