【问题标题】:Count the number of matched terms in a text file?计算文本文件中匹配项的数量?
【发布时间】:2013-12-19 08:35:56
【问题描述】:

我正在尝试从包含数据文件的每行一个术语的输入列表中计算匹配术语的数量,并创建一个包含匹配(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 等,但我不知道如何生成包含匹配项及其相应计数的输出列表。

任何建议都会很棒!

【问题讨论】:

    标签: perl unix grep match


    【解决方案1】:

    您可以从 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。但是,我更喜欢使用 paste 来获得所需的格式。比如:paste -d' ' input.txt &lt;(cut -d' ' -f2 input.txt | grep -o -f - data.txt | uniq -c | awk '{print $1}')
    • 此外,sort 管道在这里可能没用。
    【解决方案2】:

    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{} 块中打印输出。

    使用n(数字)r(反向)和k2(第二列)选项连接到sort,您将获得排序后的数据:

    $ 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
    

    【讨论】:

      【解决方案3】:

      您可以这样做 - 这可能是您自己的目标。它基本上使用“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
      

      【讨论】:

      • 愚蠢的问题,但是如何将输出打印到单独的文件中?谢谢
      • 做两个回声... "echo $line" 然后在下一行 "echo $n"
      • 它仍在打印到屏幕上
      • Add "> yourOutputFile" 到最后一行的最后。
      【解决方案4】:
      perl -lane '$s{ $F[3] }++ END{ print "+ $_ $s{$_}" for sort keys %s }' data.txt
      

      【讨论】:

        【解决方案5】:

        你也可以在 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
        

        【讨论】:

          猜你喜欢
          • 2023-02-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-29
          • 1970-01-01
          • 1970-01-01
          • 2016-03-08
          相关资源
          最近更新 更多