首页 > 解决方案 > awk 选择带有变量的行,无法打开没有这样的文件

问题描述

我正在努力使用基本的 awk 命令。

文件 1:

AB253828.1
AB253829.1
AB253830.1
AB253831.1

文件 2:

accession   accession.version   taxid   gi
A00001  A00001.1    10641   58418
A00002  A00002.1    9913    2
A00003  A00003.1    9913    3
A00004  A00004.1    32630   57971
A00005  A00005.1    32630   57972
A00006  A00006.1    32630   57973
A00008  A00008.1    32630   57974
A00009  A00009.1    32630   57975
A00010  A00010.1    32630   57976

两个文件都有 >1 000 000 行

如果第 2 列对应于文件 1 的模式,我想打印文件 2 的第 2 列和第 3 列我尝试了很多可能性,但没有任何工作......

for ACC in $(cat file1.txt)
do
    #ACC1=$(echo "\"$ACC\"")
    awk -v OFS='\t'-v z="$ACC" '{ if($2 == z) { print $2,$3 } }' file2.txt
done

我有

awk: 无法打开 { if($2 == z) { print $2,$3 } } file2.txt (没有这样的文件或目录)

我查了一下,file2在那里。我想,我的问题是变量 z 但我找不到解决方案。

标签: awk

解决方案


直接的问题是您在第二个-v选项之前缺少一个空格。(仔细观察:您将 OFS 设置为\t-v,然后 Awk 认为z="$ACC"是您的实际 Awk 脚本,并寻找 - 并抱怨缺少 - 一个名为 ...您的 Awk 脚本内容的文件。)但实际上,您想要彻底检查这更彻底。

awk -v OFS='\t' 'NR==FNR { z[$1]++; next }
    $2 in z { print $2,$3 }' file1.txt file2.txt

这使用常见的 Awk 习惯用法将第一个文件读入内存,然后从第二个文件中打印出第二个字段作为第一个文件中的条目存在的记录。这应该快几个数量级,当然也可以用反模式简单地修复阅读线。for

如果第一个文件太大而无法立即放入内存,则可以将其划分为较小的部分(例如每个 500,000 行?)并分别在每个文件上运行。应该很容易看出 Awk 何时消耗了如此多的内存以致您的系统开始抖动;至少在最初的几次运行中,密切关注top或一些类似的监控工具,如果它行为不端,则终止该进程。


推荐阅读