Jika Anda ingin tetap menggunakan utilitas shell, Anda dapat menggunakan head
untuk mengekstrak sejumlah byte, dan od
untuk mengubah byte menjadi angka.
export LC_ALL=C # make sure we aren't in a multibyte locale
n=$(head -c 1 | od -An -t u1)
string=$(head -c $n)
Namun, ini tidak berfungsi untuk data biner. Ada dua masalah:
Substitusi perintah $(…)
menghapus baris baru dalam output perintah. Ada solusi yang cukup mudah: pastikan output berakhir pada karakter selain dari baris baru, lalu hapus satu karakter itu.
string=$(head -c $n; echo .); string=${string%.}
Bash, seperti kebanyakan shell, buruk dalam berurusan dengan null byte . Pada bash 4.1, null byte hanya dijatuhkan dari hasil substitusi perintah. Dash 0.5.5 dan pdksh 5.2 memiliki perilaku yang sama, dan ATT ksh berhenti membaca pada byte nol pertama. Secara umum, cangkang dan utilitasnya tidak diarahkan untuk menangani file biner. (Zsh adalah pengecualian, ini dirancang untuk mendukung byte nol.)
Jika Anda memiliki data biner, Anda ingin beralih ke bahasa seperti Perl atau Python.
<input_file perl -e '
read STDIN, $c, 1 or die $!; # read length byte
$n = read STDIN, $s, ord($c); # read data
die $! if !defined $n;
die "Input file too short" if ($n != ord($c));
# Process $s here
'
<input_file python -c '
import sys
n = ord(sys.stdin.read(1)) # read length byte
s = sys.stdin.read(n) # read data
if len(s) < n: raise ValueError("input file too short")
# Process s here
'
Gilles 'SANGAT berhenti menjadi jahat'
sumber
sumber
read -N
berhenti pada byte nol, jadi ini bukan cara yang cocok untuk bekerja dengan data biner. Secara umum, cangkang selain zsh tidak dapat mengatasi nulls.Jika Anda ingin dapat menangani file biner di shell, opsi terbaik (hanya?) Adalah bekerja dengan alat hexdump .
Hanya baca X byte:
Baca panjang (dan bekerja dengan 0 sebagai panjang) dan kemudian "string" sebagai nilai desimal byte:
sumber
PEMBARUAN (dengan melihat ke belakang): ... Pertanyaan / jawaban ini (jawaban saya) membuat saya berpikir tentang anjing yang terus mengejar mobil .. Suatu hari, akhirnya, dia mengejar ke mobil .. Oke, dia menangkapnya, tapi dia benar-benar tidak bisa berbuat banyak dengan itu ... Anser ini 'menangkap' string, tetapi kemudian Anda tidak bisa berbuat banyak dengan mereka, jika mereka telah menanamkan null-byte ... (jadi +1 besar untuk Gilles menjawab .. bahasa lain mungkin ada di sini.)
dd
membaca setiap dan semua data ... Ini tentu tidak akan menghalangi nol sebagai "panjang" ... tetapi jika Anda memiliki \ x00 di mana pun dalam data Anda, Anda harus kreatif bagaimana Anda menanganinya;dd
tidak memiliki masalah dengan itu, tetapi skrip shell Anda akan memiliki masalah (tapi itu tergantung pada apa yang ingin Anda lakukan dengan data) ... Berikut ini pada dasarnya output setiap "string data", ke file dengan garis pembagi antara setiap strin ...btw: Anda mengatakan "karakter", dan saya berasumsi maksud Anda "byte" ...
tetapi kata "karakter" telah menjadi ambigu pada zaman UNICODE, di mana hanya set karakter ASCII 7-bit yang menggunakan byte tunggal per karakter ... Dan bahkan dalam sistem Unicode, jumlah byte bervariasi tergantung pada metode pengkodean karakter , misalnya. UTF-8, UTF-16, dll.
Berikut ini adalah skrip sederhana untuk menyoroti perbedaan antara "karakter" Teks dan byte.
Jika karakter panjang Anda adalah 1 byte panjang dan menunjukkan panjang byte , maka skrip ini harus melakukan trik, bahkan jika data berisi karakter Unicode ...
dd
hanya melihat byte terlepas dari pengaturan lokal apa pun ...Skrip ini digunakan
dd
untuk membaca file biner dan menampilkan string yang dipisahkan oleh pembagi "====" ... Lihat skrip berikutnya untuk data pengujiankeluar
Skrip ini membuat data uji yang mencakup awalan 3-byte per baris ...
Awalan adalah karakter Unicode tunggal berkode UTF-8 ...
sumber
/dev/urandom
sebagian besar unix. Dan data uji acak bukan data uji terbaik, Anda harus memastikan untuk mengatasi kasus-kasus sulit seperti, di sini, karakter nol dan baris baru di tempat batas.Yang ini hanya menyalin file biner:
sumber