是否可以使用awk来比较并返回两个匹配的文件的结果?
我目前正在使用:
awk 'BEGIN{FS=OFS="\t"} NR==FNR{c[$1$2]++;next};c{$1$2}>0' queryfile hitsfile
匹配命中查询和返回输出的结果,但它只返回命中文件中的列
我试过了:
awk 'BEGIN{FS=OFS="\t"} NR==FNR{c[$1$2]++;next};c{$1$2}>0 {print $1,$2,c[$1]}'
但它不起作用
我的示例数据如下所示:
queryfile
chr1 1000 1005 BDSD
chr1 1010 1015 SKK1
chr2 1015 1015 AVPR
hitsfile
chr1 1000 1005 0.5
chr1 1001 1002 0.35
chr1 1010 1015 0.4
chr1 1011 1016 0.56
chr2 1015 1015 0.1
我希望我的输出文件看起来像下面的
*output results*
chr1 1000 1005 0.5 BDSD
chr1 1010 1015 0.4 SKK1
chr2 1015 1015 0.1 AVPR
所以基本上,匹配查询的匹配将返回PLUS查询数据中的另一列。这是否可以使用awk oneliners?
另外,另一个问题是在查询文件中是否可以给出查询RANGE,并返回hitsfile中的所有行与awk的完全匹配?
通常我在R中执行这些操作,但在处理大文件和awk时速度要快得多!
谢谢!
答案 0 :(得分:1)
注意:此答案对于以前版本的问题是准确的。有关详细信息,请查看the question's revision history。
如果你在awk中设计这样的过程,你想要考虑的基本内容是要比较两个文件,其中一个文件的重要部分需要加载到内存中。如果你可以确保你使用的内存量不需要使用swap,你就会领先。 :)
所以...假设queryfile
很小且hitsfile
很大,你需要这样的东西:
$ awk '
# First, store every line of our first file in an array. Simply mentioning
# an array element is sufficient, you don't need to assign anything.
NR == FNR {
a[$0];
next;
}
# Second, walk through any remaining data (second file, third, etc),
# comparing it to elements in the array we stored in the section above.
# If the condition here is true, the default action is to print the line.
$0 in a
' queryfile hitsfile
这显然可以缩短为单线。你知道该怎么做。
这样做的最终结果是,第二个文件中的每一行都会在第一个文件中出现。通过扩展,只会打印两个文件中出现的行。
使用您在问题中提供的示例数据,我得到的输出看起来与查询文件完全相同,因为查询文件的每个项目都出现在hits文件中。
如果这不是您正在寻找的结果,请提供更详细的说明,以及您正在寻找的示例输出in your question。
替代解决方案:
您可能根本不需要使用awk。
fgrep -xf queryfile hitsfile
fgrep
命令等同于grep -F
,它比较固定字符串而不是正则表达式。 -x
选项告诉grep只考虑整行,有效地在结尾开始时锚定空值,就像正则表达式^...$
一样。 -f
选项表示匹配字符串列表应从指定文件中获取,在本例中为queryfile
。
最终结果是你有运行搜索的C代码而不是awk脚本。我会让你做基准测试,因为你有大文件,但我有兴趣了解性能差异。
答案 1 :(得分:1)
$ awk 'NR==FNR{a[$1,$2]=$4;next} ($1,$2) in a{print $0, a[$1,$2]}' queryfile hitsfile
chr1 1000 1005 0.5 BDSD
chr1 1010 1015 0.4 SKK1
chr2 1015 1015 0.1 AVPR