1

是否有内置命令可以执行此操作,或者是否有人对执行此操作的脚本有任何运气?

我正在寻找有多少行有多少特定字符出现的计数。(按出现次数降序排列)

例如,使用此示例文件:

gkdjpgfdpgdp
fdkj
pgdppp
ppp
gfjkl

建议输入(用于“p”字符)

bash/perl some_script_name "p" 示例文件

期望的输出:

occs     count
4          1
3          2
0          2

更新:您将如何编写一个解决方案来处理诸如“gd”之类的 2 个字符的字符串,而不仅仅是诸如 p 之类的特定字符?

4

6 回答 6

3
$ sed 's/[^p]//g' input.txt | awk '{print length}' | sort -nr | uniq -c | awk 'BEGIN{print "occs", "count"}{print $2,$1}' | column -t
occs  count
4     1
3     2
0     2
于 2012-04-12T12:34:07.260 回答
3

您可以将所需的字符作为 awk 的字段分隔符,然后执行以下操作:

awk -F 'p' '{ print NF-1 }' | 
  sort -k1nr | 
    uniq -c | 
      awk -v OFS="\t" 'BEGIN { print "occs", "count" } { print $2, $1 }'

对于您的示例数据,它会产生:

occs    count
4       1
3       2
0       2

如果要计算多字符串的出现次数,只需将所需的字符串作为分隔符,例如,awk -F 'gd' ...awk -F 'pp' ...

于 2012-04-12T12:38:19.600 回答
2
#!/usr/bin/env perl

use strict; use warnings;

my $seq = shift @ARGV;
die unless defined $seq;

my %freq;

while ( my $line = <> ) {
    last unless $line =~ /\S/;        
    my $occurances = () = $line =~ /(\Q$seq\E)/g;
    $freq{ $occurances } += 1;
}

for my $occurances ( sort { $b <=> $a} keys %freq ) {
    print "$occurances:\t$freq{$occurances}\n";
}

如果你想要简短,你可以随时使用:

#!/usr/bin/env perl
$x=shift;/\S/&&++$f{$a=()=/(\Q$x\E)/g}while<>
;print"$_:\t$f{$_}\n"for sort{$b<=>$a}keys%f;

或者,,perl -e '$x=shift;/\S/&&++$f{$a=()=/(\Q$x\E)/g}while<>;print"$_:\t$f{$_}\n"for sort{$b<=>$a}keys%f' inputfile但现在我越来越傻了。

于 2012-04-12T13:01:42.207 回答
2

纯重击:

declare -a count

while read ; do
  cnt=${REPLY//[^p]/}               # remove non-p characters
  ((count[${#cnt}]++))              # use length as array index
done < "$infile"

for idx in ${!count[*]}             # iterate over existing indices
do echo -e "$idx ${count[idx]}"
done | sort -nr

根据需要输出:

4 1
3 2
0 2
于 2012-04-12T13:17:00.223 回答
2

可以在一个 gawk 进程中完成(好吧,使用排序协进程)

gawk -F p -v OFS='\t' '
    { count[NF-1]++ }
    END {
        print "occs", "count"
        coproc = "sort -rn"
        for (n in count)
            print n, count[n] |& coproc
        close(coproc, "to")
        while ((coproc |& getline) > 0)
            print
        close(coproc)
    }
'
于 2012-04-12T13:34:12.870 回答
2

迄今为止最短的解决方案:

perl -nE'say tr/p//' | sort -nr | uniq -c |
   awk 'BEGIN{print "occs","count"}{print $2,$1}' |
      column -t

对于多个字符,使用正则表达式模式:

perl -ple'$_ = () = /pg/g' | sort -nr | uniq -c |
   awk 'BEGIN{print "occs","count"}{print $2,$1}' |
      column -t

这个处理重叠匹配(例如,它在“pppp”中找到 3 个“pp”而不是 2 个):

perl -ple'$_ = () = /(?=pp)/g' | sort -nr | uniq -c |
   awk 'BEGIN{print "occs","count"}{print $2,$1}' |
      column -t

原始的神秘但简短的纯 Perl 版本:

perl -nE'
   ++$c{ () = /pg/g };
}{
   say "occs\tcount";
   say "$_\t$c{$_}" for sort { $b <=> $a } keys %c;
'

于 2012-04-12T15:38:01.953 回答