Bash
提取兩個文件之間按順序交換的行的索引
我有兩個大的製表符分隔文件(>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
文件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
我想做類似於“差異”的事情,但在“組”級別(只有在它們共享相同
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
假設:
- 兩個數據框的行數相同
- 兩個數據幀是相同的(僅交換行的順序,因此如果兩者都按源排序,然後按位置排序,然後按位置排序,然後按標識符排序,那麼它們將完全相同)
- “交換”的行總是在所有列的內容方面完全匹配
由於輸入文件的大小,這是我可能會使用的罕見情況之一,
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 }
$ 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
有關更多資訊
getline
,請閱讀http://awk.freeshell.org/AllAboutGetline。即使在輸入中重複了
Identifier
和/或,上述內容也可以工作Position
,因為它正在比較兩個文件之間的所有 4 個欄位。它確實假設 Source 和 Location 值在兩個文件之間的順序相同,如範例輸入中所示。