根据与另一个文件的公共列从制表符分隔的文件中删除行

根据与另一个文件的公共列从制表符分隔的文件中删除行

我在处理基于与另一个文件的公共列的制表符分隔文件时遇到问题Column_4

第一个文件可能非常小(少于 100 行),但第二个文件将远远超过 80,000 个(两者都大约有 30 列)。

file1.txt:

Column_1    Column_2    Column_3    Column_4
A1          B1          C1          D1
A2          B2          C2          D2
A3          B3          C3          D3

file2.txt:

Column_1    Column_2    Column_3    Column_4
Aa1          Bb1          Cc1          Dd1
Aa2          Bb2          Cc2          D2
Aa3          Bb3          Cc3          Dd3

desired_output.txt:

Column_1    Column_2    Column_3    Column_4
Aa2          Bb2         Cc2          D2

我已经尝试了一系列cut,,grep等等awk,但似乎无法得到正确的结果。

最终目标是从 中删除所有不匹配的行file2.txt,然后将输出与 进行比较file1.txt

答案1

如果我很好地理解你的问题,这听起来像是一个典型的问题 join(“在公共字段上连接行”)用例:

join --header -j 4 -t $'\t' file1.txt file2.txt

每个匹配行都有 7 列。

这是我得到的结果(略有修改的数据,见下文):

Column_4    Column_1    Column_2    Column_3    Column_1    Column_2    Column_3
D2  A2  B2  C2  Aa2 Bb2 Cc2
D3  A3  B3  C3  Aa3 Bb3 Cc3
D8  A8  B8  C8  Aa8 Bb8 Cc8

(抱歉,标签在这里显示得不太漂亮):

Column_4 是您的匹配值,并且排在第一位。您可以按照您的要求比较其他列的值你的目标

如果您只需要第二个表列,请使用:

join --header  -j 4 -o 2.1,2.2,2.3,2.4 -t $'\t' file1.txt file2.txt 

但是,join期望其输入文件进行排序,因此您需要传递它们sort并首先在第四个字段上对它们进行排序:

join --header  -j 4 -o 2.1,2.2,2.3,2.4 -t $'\t' <(sort -k4 file1.txt) <(sort -k 4 file2.txt)

为了更好的演示,我建议稍微不同的源文件(哼,那是在你编辑它们之前)

文件1:

Column_1    Column_2    Column_3    Column_4
A0  B0  C0  D0
A2  B2  C2  D2
A3  B3  C3  D3
A8  B8  C8  D8

文件2:

Column_1    Column_2    Column_3    Column_4
Aa1 Bb1 Cc1 D1
Aa2 Bb2 Cc2 D2
Aa3 Bb3 Cc3 D3
Aa4 Bb4 Cc4 D4
Aa5 Bb5 Cc5 D5
Aa6 Bb6 Cc6 D6
Aa7 Bb7 Cc7 D7
Aa8 Bb8 Cc8 D8
Aa9 Bb9 Cc9 D9

答案2

解决方案awk

$ awk -F"\t" 'FNR==NR{a[$4];next}; $4 in a' OFS="\t" file1 file2
Column_1    Column_2    Column_3    Column_4
Aa2          Bb2          Cc2          D2

相关内容