1

これを行うための組み込みコマンドはありますか、それともそれを行うスクリプトで運が良かった人はいますか?

特定の文字が何行出現したかを数えたいと思っています。(出現回数の降順でソート)

たとえば、次のサンプル ファイルを使用します。

gkdjpgfdpgdp
fdkj
pgdppp
ppp
gfjkl

推奨される入力 (「p」文字の場合)

bash/perl some_script_name "p" サンプルファイル

望ましい出力:

occs     count
4          1
3          2
0          2

更新: p などの特定の文字だけでなく、「gd」などの 2 文字の文字列を処理するソリューションをどのように記述しますか?

4

6 に答える 6

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 に答える
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 に答える
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」で2つではなく3つの「pp」が見つかります)。

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 に答える
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

1つの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
#!/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 に答える