バイナリファイルでバイト発生統計を収集する方法は?


12

私は同等のものを知りたい

cat inputfile | sed 's/\(.\)/\1\n/g' | sort | uniq -c

/programming/4174113/how-to-gather-characters-usage-statistics-in-text-file-using-unix-commandsに表示され、バイナリファイルカウント用のテキストファイルでの文字使用統計の生成文字ではなく単純なバイト。つまり、出力は次の形式である必要があります。

18383 57
12543 44
11555 127
 8393 0

コマンドが文字用に参照されているものと同じ長さであるかどうかは関係ありません。

文字用のコマンドをバイナリファイルに適用すると、出力には、印刷できない文字の任意の長いシーケンスの統計が含まれます(そのための説明は求めません)。

回答:


8

GNUの場合od

od -vtu1 -An -w1 my.file | sort -n | uniq -c

または、より効率的にperl(また、発生しないバイトのカウント(0)を出力します):

perl -ne 'BEGIN{$/ = \4096};
          $c[$_]++ for unpack("C*");
          END{for ($i=0;$i<256;$i++) {
              printf "%3d: %d\n", $i, $c[$i]}}' my.file

最初の行の数字を正しく認識させるために、それぞれを追加| sort -n| sort -n -r、降順で並べる必要がありました(ソートは質問の一部ではありませんでした)。並べ替えがより適切に行われる可能性があります...
カールリヒター14

ファイル全体をソートする必要があるのは少しやり過ぎのようですが、私にとってはうまくいきました。
マイケルアンダーソン

@Karlの良い点は、要求されていませんが、sort -nここを使用する方がはるかに理にかなっています。回答が更新されました。
ステファンシャゼル

4

ソートを使用する大きなファイルの場合は遅くなります。同等の問題を解決するための短いCプログラムを作成しました(テスト付きMakefileの要点を参照)。

#include <stdio.h>

#define BUFFERLEN 4096

int main(){
    // This program reads standard input and calculate frequencies of different
    // bytes and present the frequences for each byte value upon exit.
    //
    // Example:
    //
    //     $ echo "Hello world" | ./a.out
    //
    // Copyright (c) 2015 Björn Dahlgren
    // Open source: MIT License

    long long tot = 0; // long long guaranteed to be 64 bits i.e. 16 exabyte
    long long n[256]; // One byte == 8 bits => 256 unique bytes

    const int bufferlen = BUFFERLEN;
    char buffer[BUFFERLEN];
    int i;
    size_t nread;

    for (i=0; i<256; ++i)
        n[i] = 0;

    do {
        nread = fread(buffer, 1, bufferlen, stdin);
        for (i = 0; i < nread; ++i)
            ++n[(unsigned char)buffer[i]];
        tot += nread;
    } while (nread == bufferlen);
    // here you may want to inspect ferror of feof

    for (i=0; i<256; ++i){
        printf("%d ", i);
        printf("%f\n", n[i]/(float)tot);
    }
    return 0;
}

使用法:

gcc main.c
cat my.file | ./a.out

テストはありますか?コードにはコメントがありません。一般的に、テストされていないコードを使用し、テストされていないコードまたはコメントされていないコードを公開することは、良い習慣ではありません。リビジョンをレビューする可能性もこのプラットフォームでは制限されています。明示的なコードホスティングプラットフォームを検討してください。
カールリヒター

@KarlRichterテストを追加することをお勧めします。古いバージョンが「\ 0」文字で詰まっていることがわかりました。このバージョンは動作するはずです(少なくともいくつかの基本的なテストに合格します)。
ビョルンダールグレン

fgetsバッファフルではなく行を取得します。stdinから読み取られた各行について、4096バイトのフルバッファーをスキャンしています。freadここではなく、が必要ですfgets
ステファンシャゼル

@StéphaneChazelas素晴らしい-恐怖を知らなかった(CからのI / Oはほとんどしない)。代わりにfreadを使用するように例を更新しました。
ビョルンダールグレン

ifprintfステートメントの周りにブロックを追加しました。これにより、入力ファイルに一部のバイトが含まれていない場合に出力が読みやすくなります。gist.github.com
Martin von Wittich

3

平均として、バイナリファイルの内容の統計データを判断する場合、シグマとCVはしばしば重要です。このデータをすべて、シグマからのバイト偏差のASCII円としてグラフ化するcmdlineプログラムを作成しました。
http://wp.me/p2FmmK-96
grep、xargs、およびその他のツールと併用して統計を抽出できます。 ここに画像の説明を入力してください


1

recodeプログラムは、偶数バイトのために、各種の文字セットの文字のいずれかの大きなファイル、どちらかの周波数の統計のためにすぐにこれを行うことができます。たとえば、バイトの頻度をカウントするには:

$ echo hello there > /tmp/q
$ recode latin1/..count-characters < /tmp/q
1  000A LF   1  0020 SP   3  0065 e    2  0068 h    2  006C l    1  006F o
1  0072 r    1  0074 t

注意 - 標準入力として再コーディングするファイルを指定します。指定しないと、文字頻度で静かに置き換えられます!

使用する recode utf-8/..count-characters < file入力ファイルをutf-8として扱うためにします。他にも多くの文字セットが利用可能であり、ファイルに不正な文字が含まれていると失敗します。


0

これはステファンの od答えにますが、バイトのASCII値を示しています。また、頻度/発生回数でソートされます。

xxd -c1 my.file|cut -c10-|sort|uniq -c|sort -nr

多くのプロセスが開始されるため、これは効率的ではないと思いますが、単一のファイル、特に小さなファイルには適しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.