Ідентифікація та видалення нульових символів в UNIX


98

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

  1. Визначте, які рядки у файлі містять нульові символи? Я спробував захопити \0і \x0, але це не спрацювало.

  2. Видалити нульові символи? Запуск stringsфайлу його очистив, але мені просто цікаво, чи це найкращий спосіб?


1
Таке запитання, ймовірно, належить SuperUser.com
Олів'є Лалонде

2
Насправді це питання на superuser.com: superuser.com/questions/75130/how-to-remove-ths-symbol-with-vim
jrb

Відповіді:


130

Я б використав tr:

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

Якщо вам цікаво, чи працює переадресація вводу в середині аргументів команди, це робить. Більшість снарядів буде розпізнавати і боротися з Перенаправлення вводу / виводу ( <, >, ...) де - небудь в командному рядку, на самому ділі.


і "diff файл з файлом-nulls -less-nulls" повинен показувати мені, у яких рядках були нульові символи? Це повертає набагато більше, ніж очікувалося.
собачка

10
Власне, я вважаю, що це має бути, tr -d '\000' < file-with-nulls > file-without-nullsоскільки <це частина функціональних оболонок, а не є tr.
Mikael S

9
Більшість оболонок насправді розпізнає та матиме справу з <або> в будь-якій точці аргументу. Здивував і мене.
пра

1
+1 Для використання переспрямування вводу замість cat |. Прекрасне, чисте рішення, і воно вирішило мою проблему.
Кшиштоф Яблонський

4
@Pointy '\ 000' використовується замість '\ 0' у специфікації відкритої групи POSIX для tr. Це хороший привід віддати перевагу
Гарольд Фішер

67

Використовуйте наступну команду sed для видалення нульових символів у файлі.

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

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


6
Примітка. У FreeBSD (і я вважаю також Mac OS X) sed -i потрібне розширення в наступному аргументі, але воно може бути порожнім. У цих системах, додати '', як: sed -i '' 's/\x0//g "$FILE".
Tim Čas

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

PS. Якщо ви опинитеся в оболонці Windows DOS, ви можете отримати версії GNU / win32 команд Unix від Sourceforge.net. Я ними весь час користуюся. Перевірте «od» восьмеричну дамп команду для аналізу того, що є у файлі ...
wwmbes

2

Ось приклад видалення NULL символів за допомогою ex(на місці):

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

а для кількох файлів:

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

Для рекурсивності ви можете скористатися опцією глобалізації **/*.txt (якщо вона підтримується вашою оболонкою).

Корисно для сценаріїв, оскільки sed його -iпараметр - це нестандартне розширення BSD.

Дивіться також: Як перевірити, чи файл є двійковим файлом, і прочитати всі файли, які не є?


1

Я використав:

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

щоб позбутися нулів у файлі.


0

Я зіткнувся з тією ж помилкою з:

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

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

f=cd.open(filePath,'r','utf-16')
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.