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.
STRING="௵"
echo "CHAR count is: ${#STRING}"
echo "BYTE count is: $(echo -n $STRING|wc -c)"
# CHAR count is: 1
# BYTE count is: 3 # UTF-8 ecnoded (on my system)
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 test
#
div="================================="; echo $div
((skip=0)) # read bytes at this offset
while ( true ) ; do
# Get the "length" byte
((count=1)) # count of bytes to read
dd if=binfile bs=1 skip=$skip count=$count of=datalen 2>/dev/null
(( $(<datalen wc -c) != count )) && { echo "INFO: End-Of-File" ; break ; }
strlen=$((0x$(<datalen xxd -ps))) # xxd is shipped as part of the 'vim-common' package
#
# Get the string
((count=strlen)) # count of bytes to read
((skip+=1)) # read bytes from and including this offset
dd if=binfile bs=1 skip=$skip count=$count of=dataline 2>/dev/null
ddgetct=$(<dataline wc -c)
(( ddgetct != count )) && { echo "ERROR: Line data length ($ddgetct) is not as expected ($count) at offset ($skip)." ; break ; }
echo -e "\n$div" >>dataline # add a newline for TEST PURPOSES ONLY...
cat dataline
#
((skip=skip+count)) # read bytes from and including this offset
done
#
echo
sortie
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 ...
# build test data
# ===============
prefix="௵" # prefix all non-zero length strings will this obvious 3-byte marker.
prelen=$(echo -n $prefix|wc -c)
printf \\0 > binfile # force 1st string to be zero-length (to check zero-length logic)
( lmax=3 # line max ... the last on is set to 255-length (to check max-length logic)
for ((i=1;i<=$lmax;i++)) ; do # add prefixed random length lines
suflen=$(numrandom /0..$((255-prelen))/) # random length string (min of 3 bytes)
((i==lmax)) && ((suflen=255-prelen)) # make last line full length (255)
strlen=$((prelen+suflen))
printf \\$((($strlen/64)*100+$strlen%64/8*10+$strlen%8))"$prefix"
for ((j=0;j<suflen;j++)) ; do
byteval=$(numrandom /9,10,32..126/) # output only printabls ASCII characters
printf \\$((($byteval/64)*100+$byteval%64/8*10+$byteval%8))
done
# 'numrandom' is from package 'num-utils"
done
) >>binfile
#