Si vous souhaitez vous en tenir aux utilitaires shell, vous pouvez utiliser head
pour extraire un certain nombre d'octets et od
convertir un octet en nombre.
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)
Cependant, cela ne fonctionne pas pour les données binaires. Il y a deux problèmes:
Substitution de commande $(…)
supprime les sauts de lignes finales dans la sortie de commande. Il existe une solution assez simple: assurez-vous que la sortie se termine par un caractère autre qu'une nouvelle ligne, puis supprimez ce caractère.
string=$(head -c $n; echo .); string=${string%.}
Bash, comme la plupart des shells, ne gère pas les octets nuls . Depuis bash 4.1, les octets nuls sont simplement supprimés du résultat de la substitution de commande. Dash 0.5.5 et pdksh 5.2 ont le même comportement et ATT ksh arrête la lecture au premier octet nul. En général, les shells et leurs utilitaires ne sont pas conçus pour traiter des fichiers binaires. (Zsh est l'exception, il est conçu pour prendre en charge les octets nuls.)
Si vous avez des données binaires, vous voudrez passer à un langage comme Perl ou 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- arrête d'être méchant'
la source
la source
read -N
s'arrête à des octets nuls, donc ce n'est pas une façon appropriée de travailler avec des données binaires. En général, les shells autres que zsh ne peuvent pas gérer les valeurs nulles.Si vous voulez pouvoir traiter des fichiers binaires en shell, la meilleure option (seulement?) Est de travailler avec l' outil hexdump .
Lecture seule X octets:
Lire la longueur (et travailler avec 0 comme longueur) puis "chaîne" comme valeur décimale d'octet:
la source
MISE À JOUR (avec du recul): ... Cette question / réponse (ma réponse) me fait penser au chien qui continue de courir après la voiture .. Un jour, enfin, il rattrape la voiture .. D'accord, il l'a attrapée, mais il ne peut vraiment pas faire grand-chose avec lui ... Cet anser "attrape" les cordes, mais alors vous ne pouvez pas faire grand-chose avec eux, s'ils ont intégré des octets nuls ... (donc un gros +1 à Gilles répond .. une autre langue peut être en règle ici.)
dd
lit toutes les données ... Il ne rechignera certainement pas à zéro comme une "longueur" ... mais si vous avez \ x00 n'importe où dans vos données, vous devrez être créatif sur la façon dont vous les manipulez;dd
n'a aucun problème avec cela, mais votre script shell aura des problèmes (mais cela dépend de ce que vous voulez faire avec les données) ... Ce qui suit renvoie essentiellement chaque "chaîne de données", dans un fichier avec un séparateur de ligne entre chaque strin ...btw: Vous dites "caractère", et je suppose que vous voulez dire "octet" ...
mais le mot "caractère" est devenu ambigu de nos jours d'UNICODE, où seul le jeu de caractères ASCII 7 bits utilise un seul octet par caractère ... Et même au sein du système Unicode, le nombre d'octets varie en fonction de la méthode de codage des caractères , par exemple. UTF-8, UTF-16, etc.
Voici un script simple pour mettre en évidence la différence entre un "caractère" texte et des octets.
Si votre caractère de longueur est long de 1 octet et indique une longueur d'octet , alors ce script devrait faire l'affaire, même si les données contiennent des caractères Unicode ...
dd
ne voit que les octets quel que soit le paramètre local ...Ce script utilise
dd
pour lire le fichier binaire et génère les chaînes séparées par un séparateur "====" ... Voir le script suivant pour les données de testsortie
Ce script crée des données de test qui incluent un préfixe de 3 octets par ligne ...
Le préfixe est un seul caractère Unicode codé UTF-8 ...
la source
/dev/urandom
sur la plupart des unités. Et les données de test aléatoires ne sont pas les meilleures données de test, vous devez vous assurer de traiter les cas difficiles tels que, ici, les caractères nuls et les retours à la ligne aux endroits limites.Celui-ci suffit de copier un fichier binaire:
la source