par*_*nam 3 bash diff awk file-comparison
我有两个大型制表符分隔文件(>10GB),我知道当它们排序时,它们的内容是相同的。
但是,我对行的顺序和交换的行的索引感兴趣,当它们共享相同的“键”时(此处的键定义为基于Source和Location列分组的行)。
换句话说,只有当这两个文件之间的行来自同一组时(即,当它们共享相同的源和位置时),才应相互比较。
例如,在下面的示例中,第 4、5、6 行file1.tsv应与来自的第 4、5、6 行进行比较file2.tsv
注意:文件是普通的 TSV。仅在此处添加额外的空格以使列居中和右对齐以获得更好的可见性。这些空格不是原始文件的一部分
文件1.tsv
Identifier Position Source Location
AY1:2301 87 ch1 14
BC1U:4010 105 ch1 14
AC44:1230 90 ch1 15
AJC:93410 83 ch1 16
ABYY:0001 101 ch1 16
ABC:01 42 ch1 16
HH:A9CX 413 ch1 17
LK:9310 2 ch1 17
JFNE:3410 132 ch1 18
MKASDL:11 14 ch1 18
MKDFA:9401 18 ch1 18
MKASDL1:011 184 ch2 50
LKOC:AMC02 18 ch2 50
POI:1100 900 ch2 53
MCJE:09HA 11 ch2 53
ABYCI:1123 15 ch2 53
MNKA:410 1 ch2 53
Run Code Online (Sandbox Code Playgroud)
文件2.tsv
Identifier Position Source Location
AY1:2301 87 ch1 14
BC1U:4010 105 ch1 14
AC44:1230 90 ch1 15
ABC:01 42 ch1 16
ABYY:0001 101 ch1 16
AJC:93410 83 ch1 16
HH:A9CX 413 ch1 17
LK:9310 2 ch1 17
MKASDL:11 14 ch1 18
JFNE:3410 132 ch1 18
MKDFA:9401 18 ch1 18
MKASDL1:011 184 ch2 50
LKOC:AMC02 18 ch2 50
MNKA:410 1 ch2 53
POI:1100 900 ch2 53
ABYCI:1123 15 ch2 53
MCJE:09HA 11 ch2 53
Run Code Online (Sandbox Code Playgroud)
我想做一些类似于“diff”的事情,但在“组”级别(其中仅当行共享相同的Source和时才比较行Location)
当行的顺序在同一“源/位置”“组”(或键)内“交换”时,我想提取原始的“行号” 。
整行的内容应该匹配。
但我不知道该怎么做。我只能想到编写一个 for 循环,当我的原始数据集有数百万行时,这将是极其低效的。
预期结果:
Group_Source:Location df1.index df2.index
ch1:16 4 6
ch1:16 6 4
ch1:18 9 10
ch1:18 10 9
ch2:53 14 15
ch2:53 15 17
ch2:53 17 14
Run Code Online (Sandbox Code Playgroud)
假设:
由于输入文件的大小,这是我可能会使用的罕见情况之一getline,因此我们一次只在内存中保存几行而不是> 10G:
$ cat tst.awk
BEGIN {
OFS = "\t"
print "Group_Source:Location", "df1.index", "df2.index"
}
NR != FNR { exit }
{ srcLoc = $3 ":" $4 }
srcLoc != prevSrcLoc {
if ( NR > 1 ) {
diff()
}
prevSrcLoc = srcLoc
}
{
file1[$1,$2] = FNR - 1
if ( (getline < ARGV[2]) > 0 ) {
file2[$1,$2] = FNR - 1
}
}
END { diff() }
function diff( idPos) {
for ( idPos in file1 ) {
if ( file1[idPos] != file2[idPos] ) {
print prevSrcLoc, file1[idPos], file2[idPos]
}
}
delete file1
delete file2
}
Run Code Online (Sandbox Code Playgroud)
$ awk -f tst.awk file1.tsv file2.tsv
Group_Source:Location df1.index df2.index
ch1:16 6 4
ch1:16 4 6
ch1:18 10 9
ch1:18 9 10
ch2:53 17 14
ch2:53 15 17
ch2:53 14 15
Run Code Online (Sandbox Code Playgroud)
有关 的更多信息getline,请阅读http://awk.freeshell.org/AllAboutGetline。
即使输入中重复了Identifierand/or ,上面的代码也会起作用Position,因为它比较了 2 个文件之间的所有 4 个字段。它确实假设两个文件之间的源值和位置值的顺序相同,如示例输入所示。