İkili dosyada bayt oluşum istatistikleri nasıl toplanır?


13

Eşdeğerini bilmek istiyorum

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

sunulan /programming/4174113/how-to-gather-characters-usage-statistics-in-text-file-using-unix-commands ikili dosyalar sayımı için metin dosyalarındaki karakter kullanım istatistikleri üretimi için karakterler yerine basit baytlar, yani çıktılar

18383 57
12543 44
11555 127
 8393 0

Komutun karakterler için referans verilen süre kadar alması önemli değildir.

İkili dosyalara karakterler için komut uygularsam çıktı, yazdırılamayan karakterlerin rasgele uzun dizileri için istatistikler içerir (bunun için açıklama istemiyorum).

Yanıtlar:


8

GNU ile od:

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

Veya daha verimli bir şekilde perl(ayrıca oluşmayan baytlar için bir sayı (0) verir):

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

İlk satırdaki sayıların doğru bir şekilde tanınmasını sağlamak için sırasıyla eklemem | sort -nve | sort -n -razalan düzen için (sıralama sorunun bir parçası değildi). Sıralama daha iyi yapılabilir ...
Karl Richter

Tüm dosyayı sıralamak için biraz abartılı görünüyor, ama benim için Tamam çalıştı.
Michael Anderson

İyi bir nokta @Karl, talep edilmese de, sort -nburada kullanmak çok daha mantıklı. Yanıt güncellendi.
Stéphane Chazelas

5

Büyük dosyalar için sıralama kullanmak yavaş olacaktır. Eşdeğer sorunu çözmek için kısa bir C programı yazdım ( Makefile için testlere bakın ):

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

kullanımı:

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

Testin var mı? Kodda yorum yok. Genel olarak, denenmemiş kullanmak ve denenmemiş veya yorumlanmamış kod yayınlamak iyi bir fikir değildir - ortak uygulama olup olmadığına bakılmaksızın. Düzeltmeleri gözden geçirme olasılığı da bu platformda sınırlıdır, açık bir kod barındırma platformu düşünün.
Karl Richter

@KarlRichter testleri eklemek iyi bir fikirdi. Eski versiyonu '\ 0' karakterlerinde tıkanmış buldum. Bu sürüm çalışmalıdır (en azından birkaç temel testi geçer).
Bjoern Dahlgren

fgetstampon dolu değil, bir satır alır. Stdin'den okunan her satır için 4096 baytlık tam arabelleği tarıyorsunuz. freadBurada ihtiyacın var, değil fgets.
Stéphane Chazelas

@ StéphaneChazelas harika - korkuyu bilmiyordu (nadiren C'den G / Ç). fread kullanmak için güncellenmiş örnek.
Bjoern Dahlgren

Printf deyimlerinin etrafınaif , girdi dosyasında bazı baytların oluşmaması durumunda çıktıyı daha okunabilir hale getiren bir blok ekledim : gist.github.com/martinvonwittich/…
Martin von Wittich

3

Yani, ikili dosyaların içeriğinin istatistiki verileri değerlendirilirken sigma ve CV genellikle önemlidir, tüm bu verileri sigma'dan ascii bir bayt sapması döngüsü olarak grafikleyen bir cmdline programı oluşturdum.
http://wp.me/p2FmmK-96
İstatistik çıkarmak için grep, xargs ve diğer araçlarla kullanılabilir. resim açıklamasını buraya girin


1

recodeProgram, hatta büyük dosyalar için hızlı bayt ya da çeşitli karakter setleri karakterleri için her iki frekans istatistiklerini ya bunu yapabilirsiniz. Örneğin bayt frekanslarını saymak için:

$ 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

Dikkat - dosyanızı standart girdi olarak yeniden kodlanacak şekilde belirtin, aksi takdirde sessizce karakter frekanslarıyla değiştirilir!

recode utf-8/..count-characters < fileGiriş dosyasını utf-8 olarak işlemek için kullanın . Diğer pek çok karakter kümesi kullanılabilir ve dosyada geçersiz karakterler varsa başarısız olur.


1

Bu Stephane'ın odcevabına benzer, ancak baytın ASCII değerini gösterir. Ayrıca sıklık / olay sayısına göre sıralanır.

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

Birçok işlem başlatıldığından bunun etkili olduğunu düşünmüyorum, ancak tek dosyalar, özellikle küçük dosyalar için iyi.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.