【问题标题】:Using awk to compare and print output from both files使用 awk 比较和打印两个文件的输出
【发布时间】:2015-04-28 00:01:48
【问题描述】:

是否可以使用 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]}'

但它不起作用

我的示例数据如下所示:

查询文件

chr1 1000 1005 BDSD
chr1 1010 1015 SKK1
chr2 1015 1015 AVPR

点击文件

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

因此,基本上,与查询匹配的命中加上查询数据中的另一列。这可以使用 awk oneliners 吗?

另外,另一个问题是是否有可能在查询文件中给定一个查询范围,并返回与 awk 完全匹配比较的 hitsfile 中的所有行?

通常我在 R 中执行这些操作,但是在处理大文件时速度很慢,而 awk 则要快得多!

谢谢!

【问题讨论】:

  • 这些文件有多大?您运行分析的系统的规格是什么?
  • 查询文件通常没有那么大,最多几千行。但是,命中文件的范围可以从 40 万行到几百万行不等。我试过用 R 和 awk 在 64 GB 内存的 8 核服务器上运行,与使用 which %in% 和 R 相比,awk 的速度要快得多
  • 永远不要使用c[$1$2],而是使用c[$1,$2]。想象一下输入1 2312 3 的区别。你为什么关心解决方案是否是一条线?为什么你知道数组语法在脚本的一个位置是 c[],但认为它在另一个位置是 c{}

标签: python bash shell awk


【解决方案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

【讨论】:

    【解决方案2】:

    注意:这个答案对于以前版本的问题是准确的。详情请查看the question's revision history


    如果您在 awk 中设计这样的过程,您需要考虑的基本内容是比较两个文件,其中一个文件的重要位需要加载到内存中。如果您可以确保您使用的内存量不需要使用交换,那么您将领先。 :)

    所以...假设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
    

    这显然可以缩短为单行。你已经知道该怎么做了。

    这样做的最终结果是,如果 second 文件中的每一行出现在 first 文件中,它都会被打印出来。通过扩展,只会打印两个文件中出现的行。

    使用您在问题中提供的示例数据,我得到的输出看起来与查询文件相同,因为查询文件的每个项目在 hitsfile 中出现一次。

    如果这不是您要寻找的结果,请提供更详细的解释,也许是您要寻找的示例输出,in your question

    替代解决方案

    您可能根本不需要使用 awk。

    fgrep -xf queryfile hitsfile
    

    fgrep 命令等效于grep -F,它比较固定字符串而不是正则表达式。 -x 选项告诉 grep 只考虑整行,有效地将空值锚定在结尾的开头,就像正则表达式 ^...$-f 选项表示匹配的字符串列表应取自指定文件,在本例中为 queryfile

    最终结果是您使用 C 代码而不是 awk 脚本运行搜索。我会让你做基准测试,因为你有大文件,但我想知道性能差异。

    【讨论】:

    • 嗨 ghoti,对不起,我已经更新了原始问题以获得更多说明,我想你会明白我的意思
    • 叹息。您的更新使这是一个非常不同的问题。我在答案的顶部添加了免责声明。有了 Ed 对您更新问题的简短回答,我花更多时间在这方面毫无意义。 :(
    猜你喜欢
    • 1970-01-01
    • 2020-12-13
    • 2016-07-30
    • 1970-01-01
    • 2020-04-16
    • 2017-01-31
    • 2021-06-15
    • 2012-10-18
    相关资源
    最近更新 更多