Perl
使用另一個文件從一個管道分隔文件中刪除行的 Perl 腳本有一個匹配的列
我有兩個大文件,
File A
包含所有記錄作為管道(|
)分隔的列,File B
其中有一列。我需要從
File A
該列值與File B
.我希望根據文件 A 中的第 2 列檢查文件 B 中的第 1 列
文件 B - 文件 B 中的唯一列
818815504 842019301 880702511
文件 A - 文件 A 中的第二列
2020-01-19|777504559|2|15|1|403941|53|4708267|3036|5033|127380343|0|3905585|C|1168|IRU|107|NR 2020-01-19|818815504|2|15|1|403933|8|2394063|3036|2394067|4076948618|0|15177438|B|1168|CRU|98|NK 2020-01-19|842019301|2|15|1|2|2|3712|3036|961249|65707843|65707843|8591573|B|1168|IRU|1|NJ 2020-01-19|847082255|2|15|1|2|2|284|3036|291|125650195|125650195|8870299|C|1168|IRU|1|NR 2020-01-19|858760375|2|15|1|403941|53|4708267|3036|306|99931425|0|8866849|C|1168|IRU|107|NR 2020-01-19|869323039|2|15|1|2|2|371|3036|307|106104029|106104029|4518435|C|1168|IRU|2|NR 2020-01-19|872268371|2|15|1|403941|53|4708267|3036|143|127382679|0|8866849|C|1168|IRU|107|NR 2020-01-19|858760375|2|15|1|2|2|117|3036|109|2739523|5208959|4037061|C|1168|IRU|2|NR
假設結果的順序不重要:
$ join -v 1 -t '|' -1 2 <( sort -t '|' -k2,2 fileA ) <( sort fileB ) 777504559|2020-01-19|2|15|1|403941|53|4708267|3036|5033|127380343|0|3905585|C|1168|IRU|107|NR 847082255|2020-01-19|2|15|1|2|2|284|3036|291|125650195|125650195|8870299|C|1168|IRU|1|NR 858760375|2020-01-19|2|15|1|2|2|117|3036|109|2739523|5208959|4037061|C|1168|IRU|2|NR 858760375|2020-01-19|2|15|1|403941|53|4708267|3036|306|99931425|0|8866849|C|1168|IRU|107|NR 869323039|2020-01-19|2|15|1|2|2|371|3036|307|106104029|106104029|4518435|C|1168|IRU|2|NR 872268371|2020-01-19|2|15|1|403941|53|4708267|3036|143|127382679|0|8866849|C|1168|IRU|107|NR
該
join
實用程序對給定的兩個數據集執行關係 INNER JOIN 操作。數據集必須在我們加入的列上進行排序,這就是我們在呼叫之前對文件進行排序的原因join
(如果您的 shell 不支持程序替換,請單獨對文件進行預排序)。join
我們在此處使用的選項-t '|'
和-1 2
表示“|
用作列分隔符,並在第一個數據集的第二列上連接”(第一列是預設值)。
-v 1
我們請求第一個文件中不能與第二個文件中的行配對的所有行。輸出將始終首先列出連接列,因此我們可能希望通過使用交換前兩個列將其移動到正確位置
awk
:$ join -v 1 -t '|' -1 2 <( sort -t '|' -k2,2 fileA ) <( sort fileB ) | awk 'BEGIN { FS=OFS="|" } { t=$1; $1=$2; $2=t; print }' 2020-01-19|777504559|2|15|1|403941|53|4708267|3036|5033|127380343|0|3905585|C|1168|IRU|107|NR 2020-01-19|847082255|2|15|1|2|2|284|3036|291|125650195|125650195|8870299|C|1168|IRU|1|NR 2020-01-19|858760375|2|15|1|2|2|117|3036|109|2739523|5208959|4037061|C|1168|IRU|2|NR 2020-01-19|858760375|2|15|1|403941|53|4708267|3036|306|99931425|0|8866849|C|1168|IRU|107|NR 2020-01-19|869323039|2|15|1|2|2|371|3036|307|106104029|106104029|4518435|C|1168|IRU|2|NR 2020-01-19|872268371|2|15|1|403941|53|4708267|3036|143|127382679|0|8866849|C|1168|IRU|107|NR
僅使用
awk
:$ awk -F '|' 'FNR==NR { key[$1]=1; next } !($2 in key)' fileB fileA 2020-01-19|777504559|2|15|1|403941|53|4708267|3036|5033|127380343|0|3905585|C|1168|IRU|107|NR 2020-01-19|847082255|2|15|1|2|2|284|3036|291|125650195|125650195|8870299|C|1168|IRU|1|NR 2020-01-19|858760375|2|15|1|403941|53|4708267|3036|306|99931425|0|8866849|C|1168|IRU|107|NR 2020-01-19|869323039|2|15|1|2|2|371|3036|307|106104029|106104029|4518435|C|1168|IRU|2|NR 2020-01-19|872268371|2|15|1|403941|53|4708267|3036|143|127382679|0|8866849|C|1168|IRU|107|NR 2020-01-19|858760375|2|15|1|2|2|117|3036|109|2739523|5208959|4037061|C|1168|IRU|2|NR
這首先讀取我們要提取到關聯數組中的數字
key
。然後,當解析第二個文件時,如果第二個欄位不是該數組中的鍵,則列印該行。這將按照它們在該文件中出現的順序輸出行
fileA
,但缺點是所有數字都fileB
需要保存在記憶體中。根據要求使用 Perl:
$ perl -F'\|' -le 'if (!$flag){ $key{$F[0]}=1 } elsif ($key{$F[1]}!=1) { print $_ }; if (!$flag && eof) { $flag=1 };' fileB fileA 2020-01-19|777504559|2|15|1|403941|53|4708267|3036|5033|127380343|0|3905585|C|1168|IRU|107|NR 2020-01-19|847082255|2|15|1|2|2|284|3036|291|125650195|125650195|8870299|C|1168|IRU|1|NR 2020-01-19|858760375|2|15|1|403941|53|4708267|3036|306|99931425|0|8866849|C|1168|IRU|107|NR 2020-01-19|869323039|2|15|1|2|2|371|3036|307|106104029|106104029|4518435|C|1168|IRU|2|NR 2020-01-19|872268371|2|15|1|403941|53|4708267|3036|143|127382679|0|8866849|C|1168|IRU|107|NR 2020-01-19|858760375|2|15|1|2|2|117|3036|109|2739523|5208959|4037061|C|1168|IRU|2|NR
這模仿了
awk
程序,但是由於 Perl 沒有單獨的NR
和FNR
內置的變數,我們需要維護一些狀態($flag
)來告訴我們目前是在解析第一個文件還是第二個文件。