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 比较两个文件中的两列输出匹配行 - 匹配中缺少行的主要内容,如果未能解决你的问题,请参考以下文章