【问题标题】:Adding file name to the counted data将文件名添加到计数数据
【发布时间】:2018-12-17 05:13:20
【问题描述】:

假设我有类似以下的文件。

文件 1

1,144931087,144931087,T,C  
16,89017167,89017167,C,G  
17,7330235,7330235,G,T  
17,10222478,10222478,C,T  

文件 2

1,144931087,144931087,T,C
16,89017167,89017167,C,G
17,10222478,10222478,C,T

文件 3

17,10222478,10222478,C,T  

我想知道每个文件中有多少次重复值,所以理想情况下,输出应该是这样的:

输出

2 1,144931087,144931087,T,C  
2 16,89017167,89017167,C,G  
3 17,10222478,10222478,C,T  
1 17,7330235,7330235,G,T 

我使用以下命令计算重复值。

sort Test1.csv Test2.csv Test3.csv | uniq --count

现在我想为计数的输出添加文件名。 我想要的输出应该是这样的:

Test1 Test2 2 1,144931087,144931087,T,C  
Test1 Test2 2 16,89017167,89017167,C,G  
Test1 Test2 Test 3 3 17,10222478,10222478,C,T  
Test1 1 17,7330235,7330235,G,T  

谁能帮我获得所需的输出,或者谁能建议我更好的方法来获得所需的输出?

【问题讨论】:

    标签: unix awk compare comparison string-comparison


    【解决方案1】:

    使用 awk。对不起我聪明的文件命名方案:

    $ awk '{
        a[$0]++                   # count hits
        b[$0]=b[$0] FILENAME " "  # store filenames
    }
    END {
        for(i in a)               
            print b[i] a[i],i     # output them
    }' foo bar baz
    foo bar 2 1,144931087,144931087,T,C
    foo bar 2 16,89017167,89017167,C,G
    foo bar baz 3 17,10222478,10222478,C,T
    foo 1 17,7330235,7330235,G,T
    

    更新每 cmets:

    $ awk 'BEGIN {
        FS=OFS=","
    } 
    {
        a[$1 OFS $2 OFS $3 OFS $4]++ 
        b[$1 OFS $2 OFS $3 OFS $4]=b[$1 OFS $2 OFS $3 OFS $4] FILENAME "|"
        c[$1 OFS $2 OFS $3 OFS $4]=$0                      # keep the last record with 
    }                                                      # specific key combination 
    END { 
        for(i in a) 
            print b[i] "," a[i],c[i]  
    }' foo  bar baz
    foo|bar|,2,16,89017167,89017167,C
    foo|,1,17,7330235,7330235,G
    foo|bar|,2,1,144931087,144931087,T
    foo|bar|baz|,3,17,10222478,10222478,C
    

    【讨论】:

    • 有没有办法在计数之前添加分隔符,例如 foo bar |2 1,144931087,144931087,T,C
    • 当然。将print ... 替换为print b[i] "|" a[i],i 应该可以。
    • 在我看到你的评论之前你已经这样做了。
    • 我们能否对前 4 列执行相同的操作,例如比较例如我的文件包含 10 列,但我只想比较前 4 列
    • 您将分隔符设置为,,而不是处理$0,您单独声明要处理的列,即。 $1,$2,$3,$4.
    【解决方案2】:

    输入:

    more Test*.csv
    ::::::::::::::
    Test1.csv
    ::::::::::::::
    1,144931087,144931087,T,C
    16,89017167,89017167,C,G
    17,7330235,7330235,G,T
    17,10222478,10222478,C,T
    ::::::::::::::
    Test2.csv
    ::::::::::::::
    1,144931087,144931087,T,C
    16,89017167,89017167,C,G
    17,10222478,10222478,C,T
    ::::::::::::::
    Test3.csv
    ::::::::::::::
    17,10222478,10222478,C,T
    

    命令:

    awk '{tmp[$0]++;if(length(tmp2[$0])==0){tmp2[$0]=FILENAME;next}tmp2[$0]=tmp2[$0] OFS FILENAME}END{for(elem in tmp){print tmp2[elem] OFS tmp[elem] OFS elem}}' Test*.csv
    

    输出:

    Test1.csv Test2.csv 2 1,144931087,144931087,T,C
    Test1.csv Test2.csv 2 16,89017167,89017167,C,G
    Test1.csv Test2.csv Test3.csv 3 17,10222478,10222478,C,T
    Test1.csv 1 17,7330235,7330235,G,T
    

    解释:

      # gawk profile, created Mon Dec 17 14:46:47 2018
    
      # Rule(s)
    
       {
               tmp[$0]++ #associative array to count the occurrences freq
               if (length(tmp2[$0]) == 0) {  #when you add the first occurrence filename you do not need to add a space
                       tmp2[$0] = FILENAME
                       next
                }
               #append to variable with a space
               tmp2[$0] = tmp2[$0] OFS FILENAME
        }
    
        # END rule(s)
    
        END {
               # loop on each element of the associative arrays and print them
               for (elem in tmp) {
                       print tmp2[elem] OFS tmp[elem] OFS elem
                }
        }
    

    if...next... 可以替换为(length(tmp2[$0]) == 0 ? tmp2[$0] = FILENAME : tmp2[$0] = tmp2[$0] OFS FILENAME) 以将awk 脚​​本简化为:

      {
           tmp[$0]++
           (length(tmp2[$0]) == 0 ? tmp2[$0] = FILENAME : tmp2[$0] = tmp2[$0] OFS FILENAME)
      }
    
      END {
             for (elem in tmp) {
                  print tmp2[elem] OFS tmp[elem] OFS elem
             }
      }
    

    【讨论】:

    • 感谢艾伦,感谢您的详细解释
    【解决方案3】:

    您能否尝试以下操作,这应该会给您输出到 Input_file 行的 Input 出现。我使用了gsub(/[[:space:]]+$/,""),因为您的 Input_file(s) 在最后一行有空格,因此在此处删除它们,如果不是这种情况,您可以将其删除。

    awk '
    {
      gsub(/[[:space:]]+$/,"")
    }
    !a[$0]++{
      b[++count]=$0
    }
    {
      c[$0]++
      d[$0]=d[$0]?d[$0] OFS FILENAME:FILENAME
    }
    END{
      for(i=1;i<=count;i++){
        print d[b[i]]"|"c[b[i]],b[i]
      }
    }'  test1 test2 test3
    

    输出如下。

    test1 test2|2 1,144931087,144931087,T,C
    test1 test2|2 16,89017167,89017167,C,G
    test1|1 17,7330235,7330235,G,T
    test1 test2 test3|3 17,10222478,10222478,C,T
    

    【讨论】:

    • 很高兴它对您有所帮助,您可以为所有有用的答案投票,干杯。
    • 当然可以,我还有一个疑问,我们可以计算前 4 列的重复项和文件名
    • @ManojkumarK,你能给我举个例子吗?
    • 使用我在这里给出的示例我想比较示例中给出的 5 列中的 1,144931087,144931087 现在我只想比较前 3 列
    【解决方案4】:

    另一个使用 Perl 的答案。

    > cat file1m.csv
    1,144931087,144931087,T,C
    16,89017167,89017167,C,G
    17,7330235,7330235,G,T
    17,10222478,10222478,C,T
    > cat file2m.csv 
    1,144931087,144931087,T,C
    16,89017167,89017167,C,G
    17,10222478,10222478,C,T
    > cat file3m.csv
    17,10222478,10222478,C,T
    > cat uniq_perl.ksh
    perl -lne ' 
    @t=@{ $kvf{$_} };
    if( not $ARGV ~~ @t ) { push(@t,$ARGV); $kvf{$_}=[ @t ] ;  }
    close(ARGV) if eof; 
    END { for(keys %kvf) { @x=@{$kvf{$_}};  print join(" ",@x)." ".scalar(@x)." ".$_  } }   
    ' file*m*csv 
    > ./uniq_perl.ksh
    file1m.csv file2m.csv file3m.csv 3 17,10222478,10222478,C,T
    file1m.csv 1 17,7330235,7330235,G,T
    file1m.csv file2m.csv 2 1,144931087,144931087,T,C
    file1m.csv file2m.csv 2 16,89017167,89017167,C,G
    > 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-29
      • 1970-01-01
      相关资源
      最近更新 更多