Как я могу найти двоичные данные в моем текстовом файле?
У меня есть огромный файл журнала (несколько ГБ), но почему-то там есть двоичные данные (это раздражает grep), чего, конечно, быть не должно.
Я знаю, как я могу прочитать файл в любом случае.
Я не знаю, как найти в нем плохие двоичные данные, так что я могу точно определить, где они записаны, просматривая текст вокруг них?
4 ответа
Я только что столкнулся с той же проблемой (хотя это всего лишь файл журнала размером в несколько мегабайт). Как и во многих других проблемах, для этого требуется всего лишь несколько команд.
cmp /path/to/file.log <(strings /path/to/file.log)
сравнивает файлы и сообщает вам, чем они отличаются (в отличие от diff, который сообщает вам, чем они отличаются). возвращает действительные текстовые строки из двоичных файлов.<(…)
позволяет обрабатывать вывод команды как файловый дескриптор другой команды.
По сути, вы сравниваете файл журнала с текстовыми строками в файле журнала, чтобы определить, где они в первую очередь отличаются.
Например, я получаюA and B differ: byte 1450315, line 6390
. Бегtail -n +6390 /path/to/file.log | less
показывает журнал, начиная с «плохой» строки, или вы можете передать его по конвейеру| hexdump -C | less
чтобы увидеть шестигранник (проходя черезhead -n 1
у меня не сработало, потому что двоичный файл был\x00
символы, которые отображались только при наличии пейджера)
(Примечание. Это может не работать с многогигабайтными журналами, если на компьютере недостаточно памяти — я не знаю, насколько эффективно использование памяти.strings
иcmp
являются)
Я решил ту же проблему. Что сработало для меня, так это просто
head
файл постепенно и grep его, чтобы увидеть, в какой строке встречаются двоичные символы.
Вначале я позвонил
head -n 1
, не было двоичного символа. потом
head -n 2
, тогда
head -n 3
... и так далее. Вскоре я нашел строку, где присутствовал двоичный символ.
Если у вас естьmy_file
который содержит (в):
test data 1
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@test data 2
test data 3
grep
беспокоит нулевой байт (шестнадцатеричное значение 00, представленное как^@
вvim
). Если вы ищете обычную строку «данные» с помощью$ grep 'data' my_file
Вы получаетеBinary file my_file matches
что не является ожидаемым результатом. Если вы хотите проверить/удалить нулевые байты вручную, вы можете найти байты-нарушители с помощью:
$ < my_file hexdump -C | grep -C2 ' 00'
00000000 74 65 73 74 20 64 61 74 61 20 31 0a 00 00 00 00 |test data 1.....|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 74 65 |..............te|
00000020 73 74 20 64 61 74 61 20 32 0a 74 65 73 74 20 64 |st data 2.test d|
00000030 61 74 61 20 33 0a |ata 3.|
и увидите обычные строки рядом с нулевыми байтами, которые затем можно искать в vim и редактировать (не ищите точки; они представляют собой пробельные символы, такие как новая строка и нулевой байт, а не литерал.
.) Если вы хотите удалить их программно:
$ < my_file sed 's/\x0//g' > my_file_without_nulls
Опираясь на замечательную идею @ibboard:find-non-printable.sh
:
#!/bin/sh
usage="$0 FILE - Locates first non-printable byte, as in 'FILE - differ: byte 21881, line 507'";
n_bytes=$(stat --printf='%s' "$1");
# -w: --include-all-whitespace
strings -w "$1" | cmp -n "$n_bytes" "$1";
- Нет вывода, если не найдены непечатаемые символы, вместо сообщения типа
cmp: EOF on FILE after byte 1677, line 47
. - Простая труба вместо использования
<()
. Работает с оболочкой POSIX вместо использования Bash или ZSH. Выходные данные показывают-
как имя файла вместо/dev/...
. - Работает должным образом, если файл содержит пустые строки. Для этого требуется реализация, поддерживающая
-w
, например GNUstrings
. Без этого результат просто указывает на первую пустую строку, что часто не является желаемым результатом. - Пользователю необходимо ввести имя файла только один раз.