Perl
如果文件 B 中的行與文件 A 中的多個列匹配,則刪除文件 A 中的行
這是我在這個網站上提出的第一個問題,所以如果我解釋得不好,請原諒。我也是新手。我研究了一些 perl 和 unix 命令行的東西,但就是不知道如何解決這個問題。
我有 2 個文件 - 文件 A 是包含 10 多列和大約 15,000 行的主文件,文件 B 包含 4 列和大約 1500 行。
我想一次取文件 B 中的每一行,並將這些列與文件 A 中的相應列匹配(這兩個文件之間的順序不同,但列標題相同)。如果文件 A 中文件 B 的所有 4 列都匹配,則從文件 A 中刪除該整行,並將其放入新文件(文件 C)中。
例子:
文件 A
individual_id study_id.x chromosome g_start gene referencel1hs SampleFile_num id sample_name 54 Baillie2011 4 57497067 na no 612 612 DonorAR2 54 Baillie2011 X 154790187 TMLHE no 612 612 DonorAR2 54 Baillie2011 5 159351203 ADRA1B no 612 612 DonorAR2 54 Baillie2011 13 79259801 na no 612 612 DonorAR2 54 Baillie2011 8 4452925 CSMD1 no 610 610 DonorAH
文件 B
study_id.x sample_name chromosome g_start Baillie2011 DonorAH 8 4452925 Baillie2011 DonorBC 9 5491376 Baillie2011 DonorAH 8 5829283 Baillie2011 DonorCH 8 5829283
結果:
文件 A
individual_id study_id.x chromosome g_start gene referencel1hs SampleFile_num id sample_name 54 Baillie2011 4 57497067 na no 612 612 DonorAR2 54 Baillie2011 X 154790187 TMLHE no 612 612 DonorAR2 54 Baillie2011 5 159351203 ADRA1B no 612 612 DonorAR2 54 Baillie2011 13 79259801 na no 612 612 DonorAR2
文件 C
individual_id study_id.x chromosome g_start gene referencel1hs SampleFile_num id sample_name 54 Baillie2011 8 4452925 CSMD1 no 610 610 DonorAH
perl -MFatal='open,close' -ali -ne ' if ( @ARGV ) { # FileB readin if ( $. == 1 ) { push @names, @F; } else { push @A, join $/, @F; } print; } else { # FileA readin if ( $. == 1 ) { open FILEC, ">", "FileC.out"; print FILEC $_; print; @remap = map { my $n = $names[$_]; grep { $n eq $F[$_] } 0 .. $#F; } 0..$#names; } else { my $n = join $/, @F[@remap]; if ( grep { $n eq $_ } @A ) { print FILEC $_; } else { print; } } } eof and $. = 0; eof() and close FILEC; ' FileB FileA
解釋
我們按順序向 Perl 的命令行提供 2 個文件“FileB”和“FileA”。
在讀取 FileB 期間,根據我們是在第一行還是其他行,我們會做兩件事:
- 對於 FileB 的第一行,我們將 FileB 欄位的名稱儲存到數組
@names
中。- 對於其他行,我們使用由預設情況下提供
@A
的換行符連接的欄位填充數組。\n``$/``RS
- 在這兩種情況下,我們將這些行列印到 STDOUT,以便 FileB 在
Perl
’-i
模式下被非破壞性地讀取。現在,當我們讀取 FileA 時,在它的第一行,打開一個寫入文件句柄
FILEC
,以便我們能夠填寫FileC.out
文件。
- 我們列印到 STDOUT,因為我們希望 FileB 中的這一行保留。
- 我們還列印到文件句柄 FILEC,因為我們希望標頭也進入 FileC.out。
- 現在這是關鍵步驟,其中將 FileB 的欄位映射到 FileA 的欄位。
對於 FileA 中的非第一行,我們使用數組中 FileB 中已儲存的數據對這些重新映射的欄位執行相等性檢查
@A
。如果找到匹配項,則將此行寫入 FileC.out 但不要寫入 FileA。如果未找到匹配項,則我們寫入 FileA 但不在 FileC.out 中。
在任一文件的 eof 後,我們將行計數器重置
$.
為 0,以便可以執行兩個文件的第一行相等性檢查。在最終的 eof(通過 eof() 檢測到)時,我們關閉文件句柄 FILEC。
該模組
Fatal.pm
已載入open
並close
具有對這些操作執行自動退出的功能。