Выявление и удаление нулевых символов в UNIX

99

У меня есть текстовый файл, содержащий нежелательные нулевые символы (ASCII NUL, \0). Когда я пытаюсь просмотреть это, viя вижу ^@символы, чередующиеся в обычном тексте. Как я могу:

  1. Определите, какие строки в файле содержат нулевые символы? Я пробовал использовать grepping для \0и \x0, но это не сработало.

  2. Удалить нулевые символы? Запуск stringsфайла очистил его, но мне просто интересно, лучший ли это способ?

кендырь
источник
1
Этот вопрос, вероятно, принадлежит SuperUser.com
Оливье Лалонд
2
Фактически, этот вопрос находится на superuser.com: superuser.com/questions/75130/how-to-remove-ths-symbol-with-vim
jrb

Ответы:

132

Я бы использовал tr:

tr < file-with-nulls -d '\000' > file-without-nulls

Если вам интересно, работает ли перенаправление ввода в середине аргументов команды, то да. Большинство снарядов будет распознавать и бороться с Перенаправление ввода / вывода ( <, >, ...) где - нибудь в командной строке, на самом деле.

Заостренный
источник
и «файл сравнения с файлом без нулей» должен показать мне, в каких строках есть нулевые символы? Это приносит намного больше, чем ожидалось.
dogbane
10
На самом деле, я считаю, что это должно быть, tr -d '\000' < file-with-nulls > file-without-nullsпоскольку <это часть функциональности оболочки оболочки, а не tr.
Mikael S
9
Большинство оболочек фактически распознают и обрабатывают <или> в любом месте строки аргумента. Меня тоже удивило.
pra
1
+1 За использование перенаправления ввода вместо cat |. Прекрасное, чистое решение, и оно решило мою проблему.
Krzysztof Jabłoński
4
@Pointy '\ 000' используется вместо '\ 0' в спецификации POSIX opengroup для tr. Это хорошая причина предпочесть его
Гарольд Фишер
68

Используйте следующую команду sed для удаления нулевых символов в файле.

sed -i 's/\x0//g' null.txt

это решение редактирует файл на месте, что важно, если файл все еще используется. передача -i'ext 'создает резервную копию исходного файла с добавленным суффиксом' ext '.

rekha_sri
источник
6
Примечание. Во FreeBSD (и я считаю, что также в Mac OS X) в следующем аргументе sed -i требуется расширение, но оно может быть пустым. В этих системах, добавить '', как: sed -i '' 's/\x0//g "$FILE".
Тим
1
Это на порядок быстрее, чем trу меня
диаходелический
Для меня, используя Git для Windows и $ sed --version-> sed (GNU sed) 4.7, мне пришлось использовать следующий вызов, чтобы получить файл резервной копии с именем example.csv.bak:sed -i.bak 's/\x0//g' example.csv
Эндрю Китон,
1
@ TimČas, ты отлично справился, только что пропустил одно ', поэтому он должен быть sed -i' '' s / \ x0 // g 'some_file.xml
Дарко
@ Дарко Так я и сделал. Ой.
Тим Час
22

Большое количество нежелательных символов NUL, скажем, по одному через каждый байт, указывает на то, что файл закодирован в UTF-16 и что вы должны использовать его iconvдля преобразования в UTF-8.

Игнасио Васкес-Абрамс
источник
1
Во время записи моего приложения у меня закончилось место на диске. Это приводит к этим персонажам.
dogbane
Например, он работает с помощью этой команды: iconv -f UTF-16 -t UTF-8 file.
djule5
7

Я обнаружил следующее, которое выводит, какие строки, если таковые имеются, имеют нулевые символы:

perl -ne '/\000/ and print;' file-with-nulls

Кроме того, восьмеричный дамп может сказать вам, есть ли нули:

od file-with-nulls | grep ' 000'
кендырь
источник
5

Если строки в файле заканчиваются на \ r \ n \ 000, то работает удаление \ n \ 000, а затем замена \ r на \ n.

tr -d '\n\000' <infile | tr '\r' '\n' >outfile
wwmbes
источник
PS. Если вы оказались в оболочке Windows DOS, вы можете получить версии команд Unix для GNU / win32 с Sourceforge.net. Я использую их постоянно. Проверьте "od" команду восьмеричного дампа для анализа
содержимого
2

Вот пример того, как удалить символы NULL с помощью ex(на месте):

ex -s +"%s/\%x00//g" -cwq nulls.txt

и для нескольких файлов:

ex -s +'bufdo!%s/\%x00//g' -cxa *.txt

Для рекурсивности вы можете использовать опцию подстановки **/*.txt (если она поддерживается вашей оболочкой).

Полезно для написания сценариев, так как sed его -iпараметр является нестандартным расширением BSD.

См. Также: Как проверить, является ли файл двоичным файлом, и прочитать все файлы, которых нет?

Kenorb
источник
1

Я использовал:

recode UTF-16..UTF-8 <filename>

чтобы избавиться от нулей в файле.

logisec
источник
0

Я столкнулся с той же ошибкой:

import codecs as cd
f=cd.open(filePath,'r','ISO-8859-1')

Я решил проблему, изменив кодировку на utf-16

f=cd.open(filePath,'r','utf-16')
Мин Янг
источник