AWK 比较两个文件中的两列输出匹配行 - 匹配中缺少行

Posted

技术标签:

【中文标题】AWK 比较两个文件中的两列输出匹配行 - 匹配中缺少行【英文标题】:AWK comparing two columns in two files output matching row - missing rows from matches 【发布时间】:2018-10-25 18:23:24 【问题描述】:

我有两个 txt 文件(制表符分隔)我正在尝试与 awk 进行比较。我想将 file1 的第 1 列与 file2 的第 5 列进行比较,并且任何时候 file1 第 1 列中的字符串与 file2 第 5 列匹配时,我都想打印(最终打印到新的 txt 文件)file2 的整行。文件 1 中有大约 14000 行,只有一列,文件 2 中有 40000 行,有 6 列。以下是我一直在使用的一些测试文件,试图弄清楚如何使用 awk 来获得我想要的输出。

文件1

AAGAB
AAK1
AAMDC
AAMP
AAR2
AARD
AARS

文件2

chr22   38035683    38052050    NM_018957   AAMDC   +
chrX    47001614    47004609    NM_019056   AAMP    -
chr9    21994789    22077889    NR_047539   AAR2    +
chr16   20370491    20416033    NM_174924   AARD    -
chr1    210111518   210337633   NM_001146262    AARS    +
chrX    30233674    30238206    NM_002364   MAGEB2  +
chrX    30261847    30270155    NM_002363   MAGEB1  +

我已经尝试从 SO 上的大量类似 awk 问题中采用具有类似期望输出的其他一些 awk 问题:

awk -F '\t' 'NR==FNRc[$1]++;nextc[$5]' file1 file2

但我只得到了 AARS 行的一个匹配项,即使测试文件中还有其他匹配项:

chr1    210111518   210337633   NM_001146262    AARS    +

我正在寻找的输出是:

chr14   94463615    94473898    NR_024182   AAGAB   +
chr10   74033676    74035797    NM_019058   AAK1    +
chr22   38035683    38052050    NM_018957   AAMDC   +
chrX    47001614    47004609    NM_019056   AAMP    -
chr9    21994789    22077889    NR_047539   AAR2    +
chr16   20370491    20416033    NM_174924   AARD    -
chr1    210111518   210337633   NM_001146262    AARS    +

我已尝试在 *** 上采用其他几篇文章,但即使存在多个其他文章,但仍然获得仅 1 场比赛的相同输出:

awk to match file1 with file2 and output matches

awk -F '\t' 'NR==FNRc[$1]; next ($5 in c)' file1 file2

Find rows with the same value in a column in two files

awk -F '\t' 'NR==FNRA[$1];next$5 in A' file1 file2

Comparing two columns in two files using awk

awk -F '\t' 'FNR==NR a[$1];next for (i in a) if ($5~i) print' file1 file2

有人可以帮我了解我的 awk 行哪里出错了吗?

我目前使用的是 GNU Awk 4.2.1,API:2.0

【问题讨论】:

您的文件很可能有其他选项卡或选项卡空间组合更改字段计数器。如果您的字段不包含空格字符,则无需指定字段分隔符。请在没有-F'\t' 的情况下运行相同的代码 在没有 -F '\t' 的情况下运行会产生相同的结果,但您的评论让我认为文件本身可能有问题。我使用 cat -v 检查任何其他制表符/空格组合,并看到在 file1 的末尾,除了 AARS 之外,file1 中每一行的末尾都有 ^M (因为我已经在 excel 中打开文件以另存为 txt文件)。因此,我使用 dos2unix 删除了 ^M awk 按预期工作,并按照您的建议删除了 -F '\t' 。非常感谢这让我抓狂! 嘿,当解决方案被证明是一个在其他看起来很好看的问题中完全没有提及的东西时,我喜欢它。 :-) 下一次,作为健全性检查,尝试像回答问题的人那样处理您的问题——将您的示例输入从 SO 复制到临时文件并在其上运行代码。 【参考方案1】:

我认为您几乎拥有它...我确实检查了-以下内容对我有用。

awk -F '\t' 'BEGIN  split("", a)  NR == FNR  a[$0] = 1; next  $5 in a' file1 file2

结果(您示例中的输出与 file2 不一致):

chr22   38035683    38052050    NM_018957   AAMDC   +
chrX    47001614    47004609    NM_019056   AAMP    -
chr9    21994789    22077889    NR_047539   AAR2    +
chr16   20370491    20416033    NM_174924   AARD    -
chr1    210111518   210337633   NM_001146262    AARS    +

FS 可能有问题,我想...您可以尝试让 FS 同时点击空格和制表符,并尝试从混乱中删除任何不可见和不可打印的字符?

awk -F '[[:blank:]]+' '
    BEGIN  split("", a) 
    NR == FNR 
        gsub(/[^[:graph:]]/, "")
        a[$0] = 1
        next
    
    
        p = $5
        gsub(/[^[:graph:]]/, "", p)
    
    p in a' file1 file2

【讨论】:

【参考方案2】:

file1 读取到关联数组。然后阅读file2 并为每一行寻找匹配项。

$ awk 'BEGINwhile(getline line<"file1") x[line]="1"; for (i=1;i<=NF;i++) if(x[$i]) print; break ' file2
chr22   38035683    38052050    NM_018957   AAMDC   +
chrX    47001614    47004609    NM_019056   AAMP    -
chr9    21994789    22077889    NR_047539   AAR2    +
chr16   20370491    20416033    NM_174924   AARD    -
chr1    210111518   210337633   NM_001146262    AARS    +

【讨论】:

【参考方案3】:

我将您的示例内容复制到“file1”和“file2”中,并将以下内容写入“script.awk”

BEGIN
    while(getline < "file1") 
        a[$1]=1
    
    close("file1")
 

    if($5 in a)
        print
    

跑步

gawk -f script.awk file2

结果是

chr22   38035683    38052050    NM_018957   AAMDC   +
chrX    47001614    47004609    NM_019056   AAMP    -
chr9    21994789    22077889    NR_047539   AAR2    +
chr16   20370491    20416033    NM_174924   AARD    -
chr1    210111518   210337633   NM_001146262    AARS    +

我的理解是正确的。 请检查。

【讨论】:

以上是关于AWK 比较两个文件中的两列输出匹配行 - 匹配中缺少行的主要内容,如果未能解决你的问题,请参考以下文章

验证两个不同表的两列完全匹配

两个文件中的AWK列匹配,打印不同的列

使用 awk 匹配两个不同文件中的数字

比较两个excel的两列并返回第三列

AWK:比较 2 个 csv 文件中的 2 列,输出到第三个。如何获得与另一个文件不匹配的输出?

R-匹配两个数据帧中的两列