Identyfikowanie i usuwanie znaków null w systemie UNIX


99

Mam plik tekstowy zawierający niechciane znaki null (ASCII NUL, \0). Kiedy próbuję to zobaczyć, viwidzę ^@symbole przeplatane zwykłym tekstem. Jak mogę:

  1. Zidentyfikować, które wiersze w pliku zawierają znaki puste? Próbowałem grepować dla \0i \x0, ale to nie zadziałało.

  2. Usunąć znaki puste? Uruchomienie stringsna pliku wyczyściło go, ale zastanawiam się tylko, czy to najlepszy sposób?


1
Tego rodzaju pytanie prawdopodobnie należy do SuperUser.com
Olivier Lalonde

2
W rzeczywistości to pytanie jest na superuser.com: superuser.com/questions/75130/how-to-remove-ths-symbol-with-vim
jrb

Odpowiedzi:


132

Użyłbym tr:

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

Jeśli zastanawiasz się, czy przekierowanie wejścia w środku argumentów poleceń działa, to działa. Większość muszle będą rozpoznawać i radzić sobie z I / O przekierowania ( <, >...) w dowolnym miejscu w wierszu poleceń, faktycznie.


a "diff file-with-nulls file-without-nulls" powinien pokazać mi, które wiersze miały puste znaki? Przynosi o wiele więcej niż oczekiwano.
zgubiony

10
Właściwie uważam, że powinno tak być, tr -d '\000' < file-with-nulls > file-without-nullsponieważ <jest częścią funkcji rury powłoki, a nie tr.
Mikael S

9
Większość powłok rozpoznaje i radzi sobie z <lub> w dowolnym miejscu argumentu. Mnie też zdziwiłem.
dniu

1
+1 Do użycia przekierowania wejścia zamiast cat |. Dobre, czyste rozwiązanie i rozwiązało mój problem.
Krzysztof Jabłoński

4
@Pointy '\ 000' jest używane zamiast '\ 0' w specyfikacji POSIX opengroup dla tr. To dobry powód, żeby go preferować
Harold Fischer

68

Użyj następującego polecenia sed, aby usunąć znaki null z pliku.

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

to rozwiązanie edytuje plik w miejscu, co jest ważne, jeśli plik jest nadal używany. przekazanie -i'ext 'tworzy kopię zapasową oryginalnego pliku z dodanym przyrostkiem' ext '.


6
Uwaga: We FreeBSD (i myślę, że także Mac OS X) sed -i wymaga rozszerzenia w następnym argumencie, ale może być puste. W tych systemach, dodać '', na przykład: sed -i '' 's/\x0//g "$FILE".
Tim Čas

1
To o rząd wielkości szybciej niż trdla mnie
diachedelic

Dla mnie, używając Git dla Windows i $ sed --version-> sed (GNU sed) 4.7, musiałem użyć następującego wywołania, aby uzyskać plik kopii zapasowej o nazwie example.csv.bak:sed -i.bak 's/\x0//g' example.csv
Andrew Keeton

1
@ TimČ, bo zrobiłeś to świetnie, właśnie przegapiłem jeden 'więc powinien być sed -i' '' s / \ x0 // g 'some_file.xml
Darko

@Darko Tak zrobiłem. Ups.
Tim Čas

22

Duża liczba niechcianych znaków NUL, powiedzmy jeden co drugi bajt, wskazuje, że plik jest zakodowany w UTF-16 i że należy go użyć iconvdo konwersji do UTF-8.


1
Skończyło mi się miejsce na dysku podczas logowania aplikacji. Spowodowało to te postacie.
zgubienie psów

Na przykład, działa za pomocą polecenia: iconv -f UTF-16 -t UTF-8 file.
djule5

7

Odkryłem następujące, które wypisuje, które wiersze, jeśli w ogóle, mają znaki puste:

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

Ponadto zrzut ósemkowy może powiedzieć, czy występują wartości null:

od file-with-nulls | grep ' 000'

5

Jeśli wiersze w pliku kończą się na \ r \ n \ 000, to działa usunięcie \ n \ 000, a następnie zastąpienie \ r \ n.

tr -d '\n\000' <infile | tr '\r' '\n' >outfile

PS. Jeśli znajdziesz się w powłoce Windows DOS, możesz pobrać wersje poleceń Unix w wersji GNU / win32 ze strony Sourceforge.net. Używam ich cały czas. Sprawdź "od" polecenie zrzutu ósemkowego do analizy zawartości pliku ...
wwmbes

2

Oto przykład, jak usunąć znaki NULL za pomocą ex(w miejscu):

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

i dla wielu plików:

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

Dla rekurencyjności możesz użyć opcji globbingu **/*.txt (jeśli jest obsługiwana przez twoją powłokę).

Przydatne do tworzenia skryptów, ponieważ sed jego -iparametr jest niestandardowym rozszerzeniem BSD.

Zobacz też: Jak sprawdzić, czy plik jest plikiem binarnym i czytać wszystkie pliki, które nim nie są?


1

Użyłem:

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

aby pozbyć się zer w pliku.


0

Napotkałem ten sam błąd z:

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

Rozwiązałem problem, zmieniając kodowanie na utf-16

f=cd.open(filePath,'r','utf-16')
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.