【问题标题】:join two files based on two columns基于两列连接两个文件
【发布时间】:2011-09-12 18:27:35
【问题描述】:

信不信由你,我在整个互联网上进行了搜索,但在 AWK 中没有找到解决此问题的有效解决方案。

我有两个文件,A 和 B:

文件 A:

chr1   pos1   
chr1   pos2
chr2   pos1
chr2   pos2

文件 B:

chr1 pos1
chr2 pos1
chr3 pos2

期望的输出:

chr1 pos1
chr2 pos1

我想加入这两个文件,以基本上根据第一列和第二列获得两个文件之间的交集,而不仅仅是第一列。既然是这种情况,大多数简单的脚本将无法工作,并且加入似乎不是一种选择。

有什么想法吗?

编辑:抱歉,我没有提到除了我展示的两列之外还有更多列。我在示例中只显示了两个,因为我只对两个文件之间的前两列相同感兴趣,其余数据并不重要(但仍然在文件中)

【问题讨论】:

    标签: bash awk


    【解决方案1】:

    嗯,我的想法是这样的: 使用join合并两个文件并用awk修正

    $ join  A B 
    chr1 pos1 pos1
    chr1 pos2 pos1
    chr2 pos1 pos1
    chr2 pos2 pos1
    
    $ join  A B | awk '{ if ($2==$3) printf("%s %s\n", $1, $2) }'
    chr1 pos1 pos1
    chr2 pos1 pos1
    

    编辑:给定编辑,加入解决方案可能仍然有效(带有选项),所以这个概念仍然正确(imo)。

    【讨论】:

    • 为什么不:join A B | awk '{ if ($2==$3) print $0 }' | awk '{ print $1 " " $2 }' 这样他就有正确的输出?
    • 我添加更正了我的答案以按要求行事。 printf 比管道其他 awk imo 要好。
    • 请注意,join 需要排序输入。这可能是也可能不是障碍。
    • 至少用GNU coreutils join,可以指定打印哪些列,所以awk可能就不需要了。
    【解决方案2】:

    awk的解决方法是:

    awk 'FILENAME==ARGV[1] {pair[$1 " " $2]; next} ($1 " " $2 in pair)' fileB fileA
    

    首先放置较小的文件,因为您基本上必须将其保存在内存中。

    【讨论】:

    • 非常好的使用FILENAME==ARVG[1]的方法。这比NR==FNR 的优势在于可以正确处理空文件。
    【解决方案3】:

    我会这样写:

    awk 'NR == FNR {
      k[$1, $2]
      next
      }
    ($1, $2) in k
      ' filea fileb  
    

    输入文件的顺序可能需要根据具体要求进行调整。

    【讨论】:

      【解决方案4】:

      为什么不像这样简单的grep -f

      grep -f fileB fileA
      

      编辑:

      对于超过 2 列的文件,试试这个:

      grep "$(cut -d" " -f1,2 fileB)" fileA | cut -d" " -f1,2
      

      【讨论】:

      • 您的编辑应该是grep -f <(cut -d " " -f 1,2 fileB) fileA | ... -- cut 命令将返回几行您希望将其视为文件而不是单个字符串的行。
      • 另外,grep -f 假定两个文件中的列间距相同,但所示示例并未显示。
      猜你喜欢
      • 2016-08-12
      • 1970-01-01
      • 1970-01-01
      • 2018-07-15
      • 2013-09-29
      • 2012-10-11
      • 2013-03-28
      • 2015-12-20
      • 1970-01-01
      相关资源
      最近更新 更多