Binaire grep sur Linux?
Dire que j'ai généré les suivantes fichier binaire:
# generate file:
python -c 'import sys;[sys.stdout.write(chr(i)) for i in (0,0,0,0,2,4,6,8,0,1,3,0,5,20)]' > mydata.bin
# get file size in bytes
stat -c '%s' mydata.bin
# 14
Et de dire, je veux trouver les emplacements de tous les zéros (0x00
), à l'aide d'un grep-syntaxe.
Le mieux que je puisse faire pour l'instant est:
$ hexdump -v -e "1/1 \" %02x\n\"" mydata.bin | grep -n '00'
1: 00
2: 00
3: 00
4: 00
9: 00
12: 00
Cependant, cette convertit implicitement chaque octet dans l'original fichier binaire dans un multi-octets ASCII de la représentation, sur lequel grep
fonctionne; pas exactement le premier exemple d'optimisation 🙂
Est là quelque chose comme un binaire grep
pour Linux? Peut-être, aussi, quelque chose qui serait en faveur d'une expression régulière comme la syntaxe, mais aussi pour les octets de "personnages" qui est, je pourrais écrire quelque chose comme " a(\x00*)b
" et de match, de zéro ou plus occurrences de l'octet 0 entre les octets 'a' (97) et " b " (98)?
EDIT: Le contexte, c'est que je suis en train de travailler sur un pilote, où j'ai fait une capture de données de 8 bits; quelque chose se passe mal dans les données, qui peut être kilo-octets jusqu'à mégaoctets, et je tiens à le consulter pour particulier signatures et où ils se produisent. (jusqu'à présent, je travaille avec des extraits de kilo-octets, de sorte que l'optimisation n'est pas important, mais si je commence à être quelques erreurs dans le mégaoctet de capture, et j'ai besoin d'analyser ces, je suppose que je voudrais quelque chose de plus optimisé 🙂 . Et surtout, je voudrais quelque chose où je peux "grep" pour un octet comme un personnage - hexdump
m'oblige à rechercher des chaînes par octet)
EDIT2: même question, les différents forum 🙂 grepping par le biais d'un fichier binaire pour une séquence d'octets
EDIT3: Merci pour la réponse par @tchrist, voici aussi un exemple avec "grepping" et de correspondance, et l'affichage des résultats (bien que pas tout à fait la même question que l'OP):
$ perl -ln0777e 'print unpack("H*",$1), "\n", pos() while /(.....$ perl -ln0777e 'print unpack("H*",$1), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin
ca000000cb000000cc000000cd000000ce # Matched data (hex)
66357 # Offset (dec)
$ perl -ln0777e 'print unpack("H*",$1), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin
ca000000cb000000cc000000cd000000ce # Matched data (hex)
66357 # Offset (dec)
$ perl -ln0777e 'print unpack("H*",$1), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin
ca000000cb000000cc000000cd000000ce # Matched data (hex)
66357 # Offset (dec)
\xCC$ perl -ln0777e 'print unpack("H*",$1), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin
ca000000cb000000cc000000cd000000ce # Matched data (hex)
66357 # Offset (dec)
$ perl -ln0777e 'print unpack("H*",$1), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin
ca000000cb000000cc000000cd000000ce # Matched data (hex)
66357 # Offset (dec)
$ perl -ln0777e 'print unpack("H*",$1), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin
ca000000cb000000cc000000cd000000ce # Matched data (hex)
66357 # Offset (dec)
.....)/g' /path/to/myfile.bin
ca000000cb000000cc000000cd000000ce # Matched data (hex)
66357 # Offset (dec)
D'avoir les données appariées être regroupés sur un seul octet (deux caractères hexadécimaux), puis "H2 H2 H2 ..." doit être spécifié pour que le nombre d'octets sont là, dans la chaîne correspondante; comme mon match " .....\0\0\0\xCC\0\0\0.....
"couvre 17 octets, je peux écrire" "H2"x17
' en Perl. Chacun de ces "H2" sera de retour d'une variable distincte (comme dans une liste), donc join
doit également être utilisés pour ajouter des espaces entre eux - par la suite:
$ perl -ln0777e 'print join(" ", unpack("H2 "x17,$1)), "\n", pos() while /(.....$ perl -ln0777e 'print join(" ", unpack("H2 "x17,$1)), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin
ca 00 00 00 cb 00 00 00 cc 00 00 00 cd 00 00 00 ce
66357
$ perl -ln0777e 'print join(" ", unpack("H2 "x17,$1)), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin
ca 00 00 00 cb 00 00 00 cc 00 00 00 cd 00 00 00 ce
66357
$ perl -ln0777e 'print join(" ", unpack("H2 "x17,$1)), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin
ca 00 00 00 cb 00 00 00 cc 00 00 00 cd 00 00 00 ce
66357
\xCC$ perl -ln0777e 'print join(" ", unpack("H2 "x17,$1)), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin
ca 00 00 00 cb 00 00 00 cc 00 00 00 cd 00 00 00 ce
66357
$ perl -ln0777e 'print join(" ", unpack("H2 "x17,$1)), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin
ca 00 00 00 cb 00 00 00 cc 00 00 00 cd 00 00 00 ce
66357
$ perl -ln0777e 'print join(" ", unpack("H2 "x17,$1)), "\n", pos() while /(.....\0\0\0\xCC\0\0\0.....)/g' /path/to/myfile.bin
ca 00 00 00 cb 00 00 00 cc 00 00 00 cd 00 00 00 ce
66357
.....)/g' /path/to/myfile.bin
ca 00 00 00 cb 00 00 00 cc 00 00 00 cd 00 00 00 ce
66357
Bien.. c'est vrai que Perl est très agréable "binaire grepping' installation, je dois l'avouer 🙂 tant Que l'on apprend la syntaxe correctement 🙂
- Pourquoi se soucier de l'optimisation? Cette question est peut-être plus facile de répondre si vous pouvez préciser un peu plus de contexte sur ce que vous essayez de faire.
- Dean: merci d'avoir soulevé la question! J'ai ajouté un edit, j'espère qu'elle clarifie! @tchrist - merci pour ça, n'avait aucune idée que je pouvais utiliser Perl pour elle 🙂 j'ai à peine trouvé la syntaxe persuader Python pour générer au niveau des octets des fichiers 🙂 (et je l'ai utilisé ici, tout simplement parce que je voulais montrer l'exact contenu du fichier, et le comportement, je suis à la recherche d')
- J'ai mis à jour ma réponse pour vous. Il devrait être plus facile à comprendre maintenant.
- Vous pouvez adapter ma technique en Perl pour la recherche de séquences d'octets, trop.
perl -ln0777e 'print pos() while /illegal/g' /usr/bin/awk
vais vous dire tous les décalages de la chaîneillegal
. Remplacer avec/\x1A\0\x43\x41/
juste pour ces quatre octets. Etc. Vous avez déjà ont binaire grepper! - merci pour la mise à jour - un binaire grepper en effet 🙂 Certainement une bonne motivation pour moi pour en savoir plus Perl.. Cheers!
- Essayé le one-liners sur un 250 GO de fichiers et perl dit "de mémoire!". Peut Perl également être utilisé pour les fichiers qui ne tiennent pas en mémoire?
Vous devez vous connecter pour publier un commentaire.
One-Liner Entrée
Voici le plus court one-liner version:
Et voici un peu plus de one-liner:
La façon de relier ces deux one-liners est par uncompiling la première du programme:
Programmée D'Entrée
Si vous souhaitez mettre ça dans un fichier au lieu de l'appeler à partir de la ligne de commande, voici un peu plus explicite version:
Et voici ce qui est vraiment long version:
One-Liner Sortie
BTW, pour créer l'entrée de test de fichier, je n'ai pas utiliser votre grand, long script Python; j'ai simplement utilisé cette Perl simple one-liner:
Vous trouverez que Perl souvent des vents est 2 à 3 fois plus court que Python pour faire le même travail. Et vous n'avez pas de compromis sur la clarté; quoi de plus simple que le one-liner au-dessus?
Sortie Programmée
Je sais, je sais. Si vous ne la connaissez pas la langue, cela peut être plus clair:
bien que cela fonctionne, trop:
comme
Bien pour ceux qui aiment tout rigoureux et attentif et tout, ce serait peut-être plus ce que vous voyez:
TMTOWTDI
Perl prend en charge plus d'une façon de faire les choses de sorte que vous pouvez choisir celui que vous êtes le plus à l'aise avec. Si c'était quelque chose que j'ai prévu de vérifier dans l'école ou le travail de projet, je serais certainement choisir le plus de temps, plus d'attention versions — ou au moins mettre un commentaire dans le script shell si j'utilisais le one-liners.
Vous pouvez trouver de la documentation de Perl sur votre système. Tapez simplement
etc dans votre invite de commande shell. Si vous voulez assez à la rigueur des versions sur le web au lieu de cela, obtenir les pages de manuel pour perl, perlrun, perlvar, et perlfunc de http://perldoc.perl.org.
perl ($/,$\) syntax
" 🙂$/
se réfère à "slurp mode" 🙂 Cheers!perl -ln0777e 'print pos() while /illegal/g' /usr/bin/awk
approche pour trouver perdu de contenu dans un disque brut de fichier de périphérique, mais perl barfed à moi avec "Out of memory" en cours.Cela semble fonctionner pour moi:
En bref:
Exemple:
De sortie (Cygwin binaire):
De sorte que vous pouvez grep ce encore pour extraire les décalages. Mais n'oubliez pas d'utiliser le mode binaire de nouveau.
grep
faire binaires avec des décalages était vraiment nécessaire, bravo!LANG=C
(précédemment LANG=pt_BR.UTF-8 et peut-être grep a été d'essayer d'interpréter les caractères unicode de mon flux d'octets).Output control
section donc... encore une fois, juste essayer avec et sans et voir la différence. Ou demander grep devs pourquoi ils ont créé une description vagueQuelqu'un d'autre ne semble avoir été de même de la frustration et de la rédaction de leur propre outil pour le faire (ou au moins quelque chose de similaire): bgrep.
La bbe programme est un sedcomme rédacteur en chef pour les fichiers binaires. Voir la documentation.
Exemple avec bbe:
Explication
Vous pouvez également vous diriger vers sed d'avoir un nettoyeur de sortie:
bbe
semble assez bon; et merci beaucoup pour la rapidité d'exemples! Cheers!Une façon de résoudre votre problème immédiat en utilisant uniquement la commande grep est de créer un fichier contenant un seul octet null. Après cela,
grep -abo -f null_byte_file target_file
produira la sortie suivante.Qui est bien sûr chaque décalage d'octet comme demandé par "-b" suivi par un octet nul, comme demandé par "-s"
Je serais le premier à défendre le perl, mais dans ce cas il n'y a pas lieu de faire appel à la famille élargie.
grep
outil !Ce sujet
grep -a
? Vous ne savez pas comment il fonctionne vraiment sur des fichiers binaires, mais il fonctionne bien sur les fichiers texte que les OS pense est binaire.grep -a
avant, mais pour rechercher des chaînes de texte (en d'autres termes, les octets dans la plage ASCII) - n'ont pas eu de chance avec trouver des séquences d'octets nuls, par exemple.. Aussi, ne sais pas si on peut convaincregrep
à la sortie de l'offset d'octet d'un match. Cheers!