Si desea seguir con las utilidades de shell, puede utilizar head
para extraer una cantidad de bytes y od
convertir un byte en un número.
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)
Sin embargo, esto no funciona para datos binarios. Hay dos problemas:
La sustitución de comandos $(…)
tiras nuevas líneas finales en la salida del comando. Hay una solución bastante fácil: asegúrese de que la salida termine en un carácter que no sea una nueva línea, luego elimine ese carácter.
string=$(head -c $n; echo .); string=${string%.}
Bash, como la mayoría de los shells, es malo para tratar con bytes nulos . A partir de bash 4.1, los bytes nulos simplemente se eliminan del resultado de la sustitución del comando. Dash 0.5.5 y pdksh 5.2 tienen el mismo comportamiento, y ATT ksh deja de leer en el primer byte nulo. En general, los shells y sus utilidades no están orientados a tratar con archivos binarios. (Zsh es la excepción, está diseñado para admitir bytes nulos).
Si tiene datos binarios, querrá cambiar a un idioma como Perl o 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 'SO- deja de ser malvado'
fuente
fuente
read -N
se detiene en bytes nulos, por lo que esta no es una forma adecuada de trabajar con datos binarios. En general, los shells que no sean zsh no pueden hacer frente a los valores nulos.Si desea poder manejar archivos binarios en shell, la mejor opción (¿solo?) Es trabajar con la herramienta hexdump .
Solo lectura X bytes:
Lea la longitud (y trabaje con 0 como longitud) y luego "cadena" como valor decimal de byte:
fuente
ACTUALIZACIÓN (en retrospectiva): ... Esta pregunta / respuesta (mi respuesta) me hace pensar en el perro que sigue persiguiendo el auto ... Un día, finalmente, se pone al día con el auto ... De acuerdo, lo atrapó, pero realmente no puede hacer mucho con eso ... Este anser 'atrapa' las cadenas, pero luego no puedes hacer mucho con ellas, si tienen bytes nulos incrustados ... (entonces un gran +1 a la respuesta de Gilles .. otro idioma puede estar en orden aquí.)
dd
lee todos y cada uno de los datos ... Ciertamente no se reducirá a cero como una "longitud" ... pero si tiene \ x00 en cualquier parte de sus datos, deberá ser creativo sobre cómo manejarlo;dd
no tiene problemas con él, pero su script de shell tendrá problemas (pero depende de lo que quiera hacer con los datos) ... Lo siguiente básicamente genera cada "cadena de datos", en un archivo con un divisor de línea entre cada cadena ...por cierto: dices "carácter", y supongo que quieres decir "byte" ...
pero la palabra "carácter" se ha vuelto ambigua en estos días de UNICODE, donde solo el conjunto de caracteres ASCII de 7 bits usa un solo byte por carácter ... E incluso dentro del sistema Unicode, los recuentos de bytes varían según el método de codificación de caracteres , por ejemplo. UTF-8, UTF-16, etc.
Aquí hay un script simple para resaltar la diferencia entre un "carácter" de texto y bytes.
Si su carácter de longitud es de 1 byte e indica una longitud de byte , entonces este script debería hacer el truco, incluso si los datos contienen caracteres Unicode ...
dd
solo ve bytes independientemente de la configuración regional ...Este script se utiliza
dd
para leer el archivo binario y genera las cadenas separadas por un divisor "====" ... Consulte el siguiente script para ver los datos de pruebasalida
Este script crea datos de prueba que incluyen un prefijo de 3 bytes por línea ...
El prefijo es un único carácter Unicode codificado en UTF-8 ...
fuente
/dev/urandom
en la mayoría de los unices. Y los datos de prueba aleatorios no son los mejores datos de prueba, debe asegurarse de abordar casos difíciles como, aquí, caracteres nulos y nueva línea en lugares de límite.Este solo copia un archivo binario:
fuente