同じバイトをグループ化してファイル内のバイト数を計算する方法は? [コピー]

同じバイトをグループ化してファイル内のバイト数を計算する方法は? [コピー]

例:「mybinaryfile」ファイルがあり、16進数の内容は次のとおりです。

A0 01 00 FF 77 01 77 01 A0

このファイルにA0バイトがいくつあるのか、01がいくつあるのかなどを知る必要があります。結果は次のとおりです。

A0: 2
01: 3
00: 1
FF: 1
77: 2

シェルで直接計算を実行する方法はありますか?または、この特定のタスクを実行するには、どの言語でプログラムを作成する必要がありますか?

答え1

これは以下を使用します。OD1行に16進数値を表示し、並べ替えて計算します。

od -t x1 -w1 -v -An mybinaryfile | sort | uniq -c

-w1拡張であり、次のように作成されていません。POSIX.)

答え2

Perlを使用してスラッピングされたファイルをバイト配列に解凍し、ハッシュを使用して一意のバイト数を計算します。

printf '\xA0\x01\x00\xFF\x77\x01\x77\x01\xA0' | 
  perl -0777 -nE '
    @bytes = unpack("C*",$_) 
    }{ 
    $counts{$_}++ for @bytes; 
    for $k (sort { $a <=> $b } keys %counts) {
      printf "%02X: %d\n", $k, $counts{$k}
    }
 '
00: 1
01: 3
77: 2
A0: 2
FF: 1

最新バージョンがList::MoreUtils利用可能な場合は、その機能を使用して計算を簡素化できますfrequency

答え3

高速Pythonソリューション:

#!/usr/bin/env python3
import sys, itertools, collections
print(
    *itertools.starmap(
        "{:02X}: {:d}".format,
        collections.Counter(sys.stdin.detach().read()).items()),
    sep="\n")

1本のライン:

python3 -c 'import sys, itertools, collections; print(*itertools.starmap("{:02X}: {:d}".format, collections.Counter(sys.stdin.detach().read()).items()), sep="\n")' \
    < input.bin

オプションと考慮事項

  • 出力を頻度で降順に並べ替えるには、次のよう.items()に置き換えます。.most_common()。または他のソート方式の場合、組み込みsorted()機能を使用するか、後処理出力を使用します。sort(1)プログラム。

  • 現在の状態では、プログラムは標準入力データ全体をバイトバッファに入れます。これは比較的小さなファイルに適しています。より大きなファイルの場合は、プログラムを次のように書き直す必要があります。ファイルをチャンク単位で読み取る

答え4

ファイルが大きい場合は、計算しながらソートできます。

od -t x1 -w1 -v -An binaryfile |
    awk '{h[$1]++} END {for (v in h) {printf "%d\t%s\n", h[v], v} }' |
    sort -k2

POSIXソリューションが必要な場合

od -t x1 -v -An binaryfile |
    tr ' ' '\n' |
    awk '$1 > "" { h[$1]++ } END { for (v in h) {printf "%d\t%s\n", h[v], v} }' |
    sort -k2

関連情報