计算文本文件中匹配的术语数量?

时间:2013-12-03 10:28:39

标签: perl unix grep match

我正在尝试计算输入列表中匹配项的数量,该列表包含每行一个术语和一个数据文件,并创建一个包含匹配(grep'd)术语和匹配数的输出文件。

input_list.txt如下所示:

+ 5S_rRNA
+ 7SK
+ AADAC
+ AC000111.3
+ AC000111.6

data.txt文件:

chr10   101780038   101780209   5S_rRNA
chr10   103578280   103578430   5S_rRNA
chr10   112327234   112327297   5S_rRNA
chr10   120766459   120766601   7SK
chr10   127408228   127408317   7SK
chr10   127511874   127512063   AADAC
chr10   14614140    14614294    AC000111.3
chr10   14695964    14696146    AC000111.6

我想创建一个输出文件(output.txt),其中包含匹配的术语及其相应的计数。

+ 5S_rRNA   3
+ 7SK   2
+ AADAC 1
+ AC000111.3    1
+ AC000111.6    1

到目前为止,我已经使用以下脚本生成了一个包含所有匹配术语的列表,但所有提供匹配术语计数的尝试均无效。

    exec < input_list.txt
    while read line
    do
                grep -w data.txt | awk '{print $0}'| sort| uniq  >> grep_output.txt
    done

我已经尝试了grep -o -w | wc -l and grep -w data.txt | wc -l等但我无法弄清楚如何生成包含匹配术语及其相应计数的输出列表。

任何建议都会很棒!

5 个答案:

答案 0 :(得分:5)

您可以使用input.txt中的单词grep并使用uniq来获取计数:

cut -d' ' -f2 input.txt | grep -o -f - data.txt | sort | uniq -c

给出:

  3 5S_rRNA
  2 7SK
  1 AADAC
  1 AC000111.3
  1 AC000111.6

您还可以添加另一个sed来获取格式化输出:

cut -d' ' -f2 input.txt | grep -o -f - data.txt | sort | uniq -c | \
      sed 's/\s*\([0-9]*\)\s*\(.*\)/+ \2\t\1/'

产地:

+ 5S_rRNA   3
+ 7SK   2
+ AADAC 1
+ AC000111.3    1
+ AC000111.6    1

答案 1 :(得分:4)

awk可能对此有好处:

$ awk 'NR==FNR {vals[$2]=$2}
       $4 in vals {count[$4]++}
       END {for (i in count) print i, count[i]}' input_list data.txt
AC000111.3 1
AC000111.6 1
5S_rRNA 3
AADAC 1
7SK 2

解释

vals[]存储input_list文件的第二个字段。然后,它检查第二个文件data.txt的第4个字段是否在任何行中,并计算count[]数组中的出现次数。最后,它将输出打印在END{}块中。

使用sort(数字)n(反向)和r(第2列)选项输入k2,您可以获得排序数据:

$ awk 'NR==FNR {vals[$2]=$2}
       $4 in vals {count[$4]++}
       END {for (i in count) print i, count[i]}' input_list data.txt | sort -rnk2
5S_rRNA 3
7SK 2
AC000111.6 1
AC000111.3 1
AADAC 1

答案 2 :(得分:2)

你可以这样做 - 这可能就是你自己前进的方向。它基本上使用“wc -l”计算匹配数,然后,如果大于零,则输出搜索字符串和匹配数:

#!/bin/bash
while read line
do
   line=${line##+ }       # Strip off leading + and space
   n=$(grep "$line" data.txt 2> /dev/null | wc -l)
   if [ $n -gt 0 ]; then
      echo $line $n
   fi
done < input_list.txt

答案 3 :(得分:2)

perl -lane '$s{ $F[3] }++ END{ print "+ $_ $s{$_}" for sort keys %s }' data.txt

答案 4 :(得分:1)

你也可以使用哈希在perl中执行此操作:

#!/usr/bin/perl
use warnings;
use strict; 

open my $list, '<', 'in.txt' or die "$!";
open my $input, '<', 'in.2.txt' or die "$!";

my @split;
my (%data, %hash, %exists);
while(<$input>){
    chomp;
    @split = split(/\s+/);
    my ($info) = $split[3];
    $data{$info}++;
}

while (<$list>){
    chomp;
    my @split = split(/\+ /);
    my ($match) = $split[1];
    $hash{$match} = 1;
}

my $count = 0;
for my $compare (keys %hash){
    if (exists $data{$compare} ){
        $exists{$compare} = $data{$compare};        
        }
 }

foreach my $c (keys %exists){
    print "+ $c: $exists{$c}\n"
}

输出:

+ 5S_rRNA: 3
+ AADAC: 1
+ 7SK: 2
+ AC000111.6: 1
+ AC000111.3: 1