Jak usunąć ten symbol „^ @” za pomocą vima?

59

Mam niektóre pliki, które są uszkodzone za pomocą tego symbolu:

^ @

To nie jest część ciągu; nie można przeszukiwać. Jak zastąpić ten symbol niczym lub jak usunąć ten symbol?

Oto przykładowy wiersz z jednego pliku:

^@F^@i^@l^@e^@n^@a^@m^@e^@ ^@ ^@ ^@ ^@ ^@ ^@ ^@ ^@ ^@ ^@:^@ ^@^M^@
mrt181
źródło

Odpowiedzi:

51

Możesz spróbować:

  • %s/<CTRL-2>//g (na zwykłych komputerach)

  • %s/<CTRL-SHIFT-2>//g (na komputerach Mac)

gdzie <CTRL-2>oznacza najpierw naciśnij CTRLna zwykłych komputerach PC, trzymając go tak, jak wciśnięty, wciśnij 2, zwolnij CTRL.

i <CTRL-SHIFT-2>oznacza, że ​​najpierw naciśnij controlkomputer Mac, trzymając go jak wciśnięty, naciśnij shiftkomputer Mac, trzymając go wciśnięty, naciśnij 2, zwolnij controli shift.

Wreszcie oba te polecenia powinny zostać %s/^@//gwyświetlone na ekranie. ^@Oznacza pojedynczy znak (bajt NULL, które inaczej nie mogłyby być wyświetlane), nie ^następuje @, więc nie można po prostu wpisać ^i @z rzędu w powyższym poleceniu.

To polecenie usuwa wszystkie ^@.

fresus
źródło
4
Natknąłem się na to pytanie / odpowiedź za pomocą powiązanego linku: To właściwie zła rada i będzie działać poprawnie tylko w nielicznych przypadkach. Lepiej jest zmienić kodowanie niż usuwać bajty zerowe. Jeśli usuniesz bajty puste, nadal możesz mieć inne znaki wielobajtowe, które są wyświetlane jako śmieci.
Mario
@Mario czy możesz nam powiedzieć więcej o zmianie kodowania? Czy jest to związane z odpowiedzią jrb poniżej?
George
Zobacz odpowiedź rpyzh poniżej. Pokazuje ładowanie pliku przy użyciu właściwego kodowania, a także zapisywanie go przy użyciu innego (chociaż odpowiedź może wymagać dodatkowych wyjaśnień). Ostatnia uwaga Jrb wystarczy, jeśli chcesz ją tylko przeczytać, ale nie, jeśli chcesz ją zapisać bez bajtów zerowych przy użyciu innego kodowania.
Mario
50

Nie sądzę, że twoje pliki są uszkodzone. Twój przykładowy wiersz wygląda tak, jakby zawierał zwykły tekst z pustymi bajtami między każdym znakiem. To sugeruje, że jest to plik tekstowy zakodowany w UTF-16, ale na początku pliku brakuje znaku kolejności bajtów. Zobacz http://en.wikipedia.org/wiki/Byte-order_mark

Załóżmy, że otwieram Notatnik, wpisuję słowo „nazwa pliku” i zapisuję jako Big-endian w Unicode. Zrzut szesnastkowy tego pliku wygląda następująco:

fe ff 00 66 00 69 00 6c 00 65 00 6e 00 61 00 6d 00 65

Jeśli otworzę ten plik w Vimie, wygląda dobrze - bajty „fe ff” informują Vima, w jaki sposób plik jest kodowany. Załóżmy teraz, że tworzę plik zawierający dokładnie tę samą sekwencję bajtów, ale bez wiodącego „fe ff”. Vim wstawia ^ @ (lub <00>, w zależności od konfiguracji) zamiast bajtów pustych; Notatnik wstawia spacje.

Zamiast więc usuwać wartości zerowe, powinieneś naprawdę chcieć, aby Vim poprawnie zinterpretował plik. Możesz poprosić Vima o ponowne załadowanie pliku z poprawnym kodowaniem za pomocą polecenia:

:e ++enc=utf16

jrb
źródło
Tak, ostatnie polecenie vima poprawnie zinterpretowało plik, ale nie usuwa nullbytes.
mrt181,
6
Aby je usunąć, wybierz inne kodowanie i ponownie zapisz plik:: set fenc = utf-8
scy
35

W rzeczywistości działało to dla mnie w vimie:

:%s/\%x00//g
jriggins
źródło
5
działa to z substitute (), ale Ctl-VCtl-Shift-2 nie.
dsummersl
Dla mnie ten sam problem, nie mogłem też <Ctrl-V><Ctrl-2>(tak jak ten z <Ctrl-Shift-2>) pracować, ale to zadziałało.
Jeff Bridgman
5
To działa dla mnie linux. „00” jest wartość ASCII hex, które można znaleźć na każdym znaku w vim, umieszczając kursor nad nim i wpisując „ga” (myślę „dostać ASCII) w trybie poleceń, czyli jako /. ASCII w wierszu poleceń vim .wikia.com / wiki /…
Casey Jones
^ Vx00 również działa. Możesz także wprowadzić 16-bitowy Unicode za pomocą ^ VuXXXX. Próbowałem \% uXXXX podczas wyszukiwania i to też zadziałało.
Edward Falk,
Będziesz moim umiłowanym człowiekiem aż do końca czasów. Z głębi serca ... dziękuję!
Gonzalo Cao
12

Ten „symbol” reprezentuje znak NULL o wartości ASCII 000.

Vim jest trudny do usunięcia, spróbuj

tr -d '\000' < file1 > file2
pavium
źródło
7

Jak zauważyli inni, są to bajty zerowe (ASCII 00). W systemie Linux sposobem wprowadzania wartości ASCII w vim jest naciśnięcie klawiszy Ctrl-V, a następnie 3-cyfrowej wartości ósemkowej dowolnego znaku. Aby zastąpić wszystkie bajty puste, użyj:

    :%s/Ctrl-V000//g

(bez spacji).

Podobnie możesz wyszukiwać wartości null za pomocą:

    /Ctrl-V000

W obu przypadkach nie będą wyświetlać zer podczas pisania, ale po wpisaniu wszystkich trzech wyświetli się ^@. Na kolorowych terminalach pokaże to na niebiesko, aby wskazać, że jest to znak kontrolny.

TheAmigo
źródło
6

FWIW, w moim przypadku musiałem użyć vima na cygwin do edycji pliku tekstowego utworzonego na komputerze Mac. Przyjęte rozwiązanie nie działało dla mnie, ale było blisko. Według strony wiki Vima na temat pracy z Unicode , istnieje różnica między wersjami BOM Big Endian i Little Endian. Musiałem więc wyraźnie powiedzieć, vimaby użyć wersji kodowania BOM Little Endian.

Dopiero po wybraniu odpowiedniego kodowania przekonwertowałem format pliku (zakończenia linii), aby dosmóc edytować plik w edytorze Windows. Próba ustawienia zresetowania formatu pliku przed określeniem kodowania wywołała u mnie smutek. Oto pełna lista poleceń, których użyłem:

:e ++enc=utf16le
:w!
:e ++ff=mac
:setlocal ff=dos
:wq
rpyzh
źródło
Cenne informacje. W moim przypadku była to endianness bajtu BOM.
Andre Albuquerque
3

Przyjęte rozwiązanie nie działało dla mnie. trZamiast tego utworzyłem vim potok pliku :

:%!tr -d '\000'

Działa to również dobrze w trybie wizualnym (po prostu wpisz :!tr -d '\000') lub w szeregu linii:

# Remove nulls from current line:
:.!tr -d '\000'

# Remove nulls from lines 3-5:
:3,5!tr -d '\000'
jnylen
źródło
2

^@ niezły znak, jeśli używasz właściwego kodowania, ale jeśli chcesz go usunąć, spróbuj:

  • tr -d '\000'
  • sed 's/\000//g'

^ M znak jest w twoich przykładowych danych

Aby przekonwertować plik na format Unix / Linux przed jakimkolwiek przetwarzaniem, spróbuj:

dos2unix filename - rhel i inne

dos2ux filename [newfilename] - HP-UX

użytkownik490343
źródło
1

Oprócz odpowiedzi @ jrb w Vimie wykrywane jest kodowanie znaków pliku na podstawie opcji kodowania plików. (zwróć uwagę na „s” na końcu kodowania plików)

Tj. W systemie Windows domyślną wartością fileencodingsopcji jest ucs-bom, co oznacza:

sprawdź, czy BOM istnieje na początku pliku.

Jeśli BOM istnieje, to „odczytaj kodowanie pliku z BOM”.

Jeśli BOM nie istnieje (w tym przypadku oznaczałoby to również, że wszystkie kodowania znaków określone w fileencodingsopcji nie pasują), to przeczytaj plik z kodowaniem znaków określonym w encodingopcji. Domyślne kodowanie znaków dla tej encodingopcji jest: latin1. Ponieważ kodowanie latin1jest jednobajtowe , wszystkie bajty w pliku są poprawnymi latin1znakami (nawet Nulznak ^@, który widzisz *).

* - właściwie ^@to znak nowej linii w tekście bufora Vima, a nie znak Nul.

Właściwym sposobem na odczytanie pliku jest ręczne wpisanie kodowania znaków jako UTF-16 (ponieważ wygląda na to, że UTF-16 jest w tym przypadku właściwym kodowaniem znaków).

colemik
źródło