Como reunir estatísticas de ocorrências de bytes no arquivo binário?

11

Eu gostaria de saber o equivalente a

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

apresentado em link para produção de estatísticas de uso de caracteres em arquivos de texto para arquivos binários contando bytes simples em vez de caracteres, isto é, a saída deve estar na forma de

18383 57
12543 44
11555 127
 8393 0

Não importa se o comando demora tanto quanto o referenciado para caracteres.

Se eu aplicar o comando para caracteres a arquivos binários, a saída contém estatísticas para sequências longas arbitrárias de caracteres não imprimíveis (não busco explicação para isso).

    
por Karl Richter 23.09.2014 / 18:38

5 respostas

7

Com o GNU od :

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

Ou mais eficientemente com perl (também gera uma contagem (0) para bytes que não ocorrem):

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

Para arquivos grandes, o uso de classificação será lento. Eu escrevi um pequeno programa em C para resolver o problema equivalente ( veja essa essência para o Makefile com testes ):

#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;
}

uso:

gcc main.c
cat my.file | ./a.out
    
por 15.06.2015 / 14:14
3

Como significa, sigma e CV são frequentemente importantes ao julgar dados estatísticos do conteúdo de arquivos binários, eu criei um programa cmdline que grava todos esses dados como um círculo ascii de desvios de byte do sigma.
link
Pode ser usado com grep, xargs e outras ferramentas para extrair estatísticas.

    
por 11.10.2015 / 22:08
1

O programa recode pode fazer isso rapidamente, mesmo para arquivos grandes, seja para estatísticas de frequência para bytes ou para caracteres de vários conjuntos de caracteres. Por exemplo. para contar as frequências de bytes:

$ 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

Cuidado - especifica seu arquivo para ser recodificado como entrada padrão, caso contrário, ele silenciosamente o substituirá pelas freqüências de caracteres!

Use recode utf-8/..count-characters < file para tratar o arquivo de entrada como utf-8. Muitos outros conjuntos de caracteres estão disponíveis e falhará se o arquivo contiver caracteres ilegais.

    
por 11.02.2016 / 18:57
0

Isso é semelhante à resposta od de Stephane, mas mostra o valor ASCII do byte. Também é classificado por frequência / número de ocorrências.

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

Eu não acho que isso seja eficiente, já que muitos processos foram iniciados, mas é bom para arquivos únicos, particularmente arquivos pequenos.

    
por 09.02.2017 / 00:51