Ini adalah solusi satu baris yang diminta (untuk shell baru-baru ini yang memiliki "substitusi proses"):
grep -o "ef be ad de" <(hexdump -v -e '/1 "%02x "' infile.bin) | wc -l
Jika tidak ada "substitusi proses" <(…)
, gunakan saja grep sebagai filter:
hexdump -v -e '/1 "%02x "' infile.bin | grep -o "ef be ad de" | wc -l
Di bawah ini adalah deskripsi terperinci dari setiap bagian dari solusi.
Nilai byte dari angka hex:
Masalah pertama Anda mudah diselesaikan:
Urutan melarikan diri itu hanya bekerja di kulit ikan.
Ubah bagian atas X
ke bawah x
dan gunakan printf (untuk sebagian besar shell):
$ printf -- '\xef\xbe\xad\xde'
Atau gunakan:
$ /usr/bin/printf -- '\xef\xbe\xad\xde'
Untuk shell yang memilih untuk tidak mengimplementasikan representasi '\ x'.
Tentu saja, menerjemahkan hex ke octal akan bekerja pada (hampir) shell apa pun:
$ "$sh" -c 'printf '\''%b'\'' "$(printf '\''\\0%o'\'' $((0xef)) $((0xbe)) $((0xad)) $((0xde)) )"'
Di mana "$ sh" adalah shell (wajar). Tetapi cukup sulit untuk tetap mengutipnya dengan benar.
File biner.
Solusi yang paling kuat adalah mengubah file dan urutan byte (keduanya) menjadi beberapa pengkodean yang tidak memiliki masalah dengan nilai karakter aneh seperti (baris baru) 0x0A
atau (byte nol) 0x00
. Keduanya cukup sulit untuk dikelola dengan benar dengan alat yang dirancang dan diadaptasi untuk memproses "file teks".
Transformasi seperti base64 mungkin tampak valid, tetapi menyajikan masalah bahwa setiap byte input mungkin memiliki hingga tiga representasi output tergantung apakah itu byte pertama, kedua atau ketiga dari posisi mod 24 (bit).
$ echo "abc" | base64
YWJjCg==
$ echo "-abc" | base64
LWFiYwo=
$ echo "--abc" | base64
LS1hYmMK
$ echo "---abc" | base64 # Note that YWJj repeats.
LS0tYWJjCg==
Hex mentransformasi.
Thats why transformasi paling kuat harus menjadi yang dimulai pada setiap batas byte, seperti representasi HEX sederhana.
Kita bisa mendapatkan file dengan representasi hex file dengan salah satu dari alat ini:
$ od -vAn -tx1 infile.bin | tr -d '\n' > infile.hex
$ hexdump -v -e '/1 "%02x "' infile.bin > infile.hex
$ xxd -c1 -p infile.bin | tr '\n' ' ' > infile.hex
Urutan byte untuk pencarian sudah dalam hex dalam hal ini.
:
$ var="ef be ad de"
Tetapi bisa juga diubah. Contoh round trip hex-bin-hex berikut:
$ echo "ef be ad de" | xxd -p -r | od -vAn -tx1
ef be ad de
String pencarian dapat diatur dari representasi biner. Salah satu dari tiga opsi yang disajikan di atas od, hexdump, atau xxd adalah setara. Pastikan untuk memasukkan spasi untuk memastikan kecocokan berada pada batas byte (tidak boleh menggeser shift):
$ a="$(printf "\xef\xbe\xad\xde" | hexdump -v -e '/1 "%02x "')"
$ echo "$a"
ef be ad de
Jika file biner terlihat seperti ini:
$ cat infile.bin | xxd
00000000: 5468 6973 2069 7320 efbe adde 2061 2074 This is .... a t
00000010: 6573 7420 0aef bead de0a 6f66 2069 6e70 est ......of inp
00000020: 7574 200a dead beef 0a66 726f 6d20 6120 ut ......from a
00000030: 6269 0a6e 6172 7920 6669 6c65 2e0a 3131 bi.nary file..11
00000040: 3232 3131 3232 3131 3232 3131 3232 3131 2211221122112211
00000050: 3232 3131 3232 3131 3232 3131 3232 3131 2211221122112211
00000060: 3232 0a
Kemudian, pencarian grep sederhana akan memberikan daftar urutan yang cocok:
$ grep -o "$a" infile.hex | wc -l
2
Satu baris?
Itu semua dapat dilakukan dalam satu baris:
$ grep -o "ef be ad de" <(xxd -c 1 -p infile.bin | tr '\n' ' ') | wc -l
Misalnya, mencari 11221122
dalam file yang sama akan membutuhkan dua langkah ini:
$ a="$(printf '11221122' | hexdump -v -e '/1 "%02x "')"
$ grep -o "$a" <(xxd -c1 -p infile.bin | tr '\n' ' ') | wc -l
4
Untuk "melihat" kecocokan:
$ grep -o "$a" <(xxd -c1 -p infile.bin | tr '\n' ' ')
3131323231313232
3131323231313232
3131323231313232
3131323231313232
$ grep "$a" <(xxd -c1 -p infile.bin | tr '\n' ' ')
… 0a 3131323231313232313132323131323231313232313132323131323231313232 313132320a
Buffering
Ada kekhawatiran bahwa grep akan buffer seluruh file, dan, jika file besar, membuat beban berat untuk komputer. Untuk itu, kami dapat menggunakan solusi sed yang tidak disatukan:
a='ef be ad de'
hexdump -v -e '/1 "%02x "' infile.bin |
sed -ue 's/\('"$a"'\)/\n\1\n/g' |
sed -n '/^'"$a"'$/p' |
wc -l
Sed pertama adalah unbuffered ( -u
) dan hanya digunakan untuk menyuntikkan dua baris baru pada aliran per string yang cocok. Keduased
hanya akan mencetak garis yang cocok (pendek). Wc -l akan menghitung garis yang cocok.
Ini hanya akan menyangga beberapa garis pendek. String yang cocok di sed kedua. Ini harus cukup rendah dalam sumber daya yang digunakan.
Atau, agak lebih kompleks untuk dipahami, tetapi ide yang sama dalam satu sed:
a='ef be ad de'
hexdump -v -e '/1 "%02x "' infile.bin |
sed -u '/\n/P;//!s/'"$a"'/\n&\n/;D' |
wc -l
grep -o