이진 파일에서 바이트 발생 통계를 수집하는 방법은 무엇입니까?


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내림차순으로 정렬해야했습니다 (정렬은 질문의 일부가 아닙니다). 정렬이 더 나을 수도 있습니다 ...
Karl Richter

전체 파일을 정렬하는 데 약간의 과잉이있는 것 같지만 제대로 작동했습니다.
Michael Anderson

좋은 지적 @ Karl은 요청하지는 않지만 sort -n여기를 사용하는 것이 훨씬 더 합리적입니다. 답변이 업데이트되었습니다.
Stéphane Chazelas

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

시험 있어요? 코드에 주석이 없습니다. 일반적으로 테스트 여부에 관계없이 테스트되지 않은 코드를 사용하고 테스트되지 않은 코드 나 주석 처리되지 않은 코드를 게시하는 것은 좋은 생각이 아닙니다. 개정판 검토 가능성도이 플랫폼에서 제한됩니다. 명시 적 코드 호스팅 플랫폼을 고려하십시오.
Karl Richter

@KarlRichter 테스트는 추가하는 것이 좋습니다. 이전 버전이 '\ 0'문자로 숨어 있습니다. 이 버전은 작동해야합니다 (적어도 몇 가지 기본 테스트는 통과 함).
Bjoern Dahlgren 2016 년

fgets버퍼가 가득 찬 라인이 아닙니다. stdin에서 읽은 각 줄에 대해 4096 바이트 전체 버퍼를 스캔하고 있습니다. 필요 fread하지 않습니다 fgets.
Stéphane Chazelas

@ StéphaneChazelas great-확산에 대해 몰랐습니다 (C에서 I / O를 거의하지 않습니다). 대신 fread를 사용하도록 예제를 업데이트했습니다.
Bjoern Dahlgren 2016 년

나는 추가 한 if: 일부 바이트가 입력 파일에서 발생하지 않는 경우에 그 출력을 더 쉽게 읽을의 printf와 문 주위에 블록을 gist.github.com/martinvonwittich/...
마틴 폰 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로 취급하는 데 사용하십시오 . 다른 많은 문자 집합을 사용할 수 있으며 파일에 잘못된 문자가 포함되어 있으면 실패합니다.


1

이것은 Stephane의 od대답 과 비슷 하지만 바이트의 ASCII 값을 보여줍니다. 빈도 / 발생 횟수별로 정렬됩니다.

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

많은 프로세스가 시작되었으므로 이것이 효율적이라고 생각하지 않지만 단일 파일, 특히 작은 파일에는 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.