İ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.