Скажем, я создал следующий двоичный файл:
# 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
И скажите, я хочу найти места всех нулей (0x00
), используя синтаксис grep-like.
Лучшее, что я могу сделать до сих пор:
$ hexdump -v -e "1/1 \" %02x\n\"" mydata.bin | grep -n '00'
1: 00
2: 00
3: 00
4: 00
9: 00
12: 00
Однако это неявно преобразует каждый байт в исходном двоичном файле в многобайтовое представление ASCII, на котором работает grep
; не совсем лучший пример оптимизации:)
Есть ли что-то вроде двоичного grep
для Linux? Возможно, также, что-то, что будет поддерживать регулярный синтаксис типа выражения, но также и для байтовых "символов", то есть я мог бы написать что-то вроде "a(\x00*)b
" и сопоставлять "ноль или более" вхождения байта 0 между байтами ' a '(97) и' b '(98)?
EDIT: контекст заключается в том, что я работаю над драйвером, где я беру 8-битные данные; что-то не получается в данных, которые могут быть килобайтами до мегабайт, и я бы хотел проверить конкретные подписи и где они происходят. (до сих пор я работаю с фрагментами килобайта, поэтому оптимизация не так важна, но если я начну получать некоторые ошибки в мегабайтных длинных захватах, и мне нужно проанализировать их, я думаю, что я хотел бы что-то более оптимизированное:). И особенно, мне хотелось бы что-то, где я могу "grep" для байта как персонажа - hexdump
заставляет меня искать строки за каждый байт)
EDIT2: тот же вопрос, другой форум:) grepping через двоичный файл для последовательности байтов
EDIT3: благодаря ответу @tchrist, вот пример с "grepping" и совпадением, и отображение результатов (хотя и не совсем такой же вопрос, как OP):
$ 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)
Чтобы согласованные данные группировались как один байт (два шестнадцатеричных символа) каждый, тогда необходимо указать "H2 H2 H2..." для количества байтов в согласованной строке; так как мой матч ".....\0\0\0\xCC\0\0\0.....
" охватывает 17 байтов, я могу написать ""H2"x17
" в Perl. Каждая из этих "H2" вернет отдельную переменную (как в списке), поэтому join
также необходимо использовать для добавления пробелов между ними - в конце концов:
$ 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 очень хороший объект двоичного grepping, я должен признать:) До тех пор, пока вы правильно изучаете синтаксис:)