Como remover este símbolo “^ @” com o vim?

59

Eu tenho alguns arquivos que estão corrompidos com este símbolo:

^ @

Não faz parte da cadeia; não é pesquisável. Como substituo este símbolo por nada ou como excluo este símbolo?

Aqui está um exemplo de linha de um arquivo:

^@F^@i^@l^@e^@n^@a^@m^@e^@ ^@ ^@ ^@ ^@ ^@ ^@ ^@ ^@ ^@ ^@:^@ ^@^M^@
mrt181
fonte

Respostas:

51

Você poderia tentar:

  • %s/<CTRL-2>//g (em computadores comuns)

  • %s/<CTRL-SHIFT-2>//g (em PCs Mac)

onde <CTRL-2>significa primeiro pressionar os CTRLPCs comuns, mantendo-os pressionados, pressionando 2, solte CTRL.

e <CTRL-SHIFT-2>significa primeiro pressionar os controlMac PCs, mantendo pressionado, pressionar shiftMac Macs, mantendo pressionado, pressionar 2, soltar controle shift.

Finalmente, os dois comandos devem resultar na %s/^@//gtela. ^@significa um único caractere (um byte NULL, que de outra forma não poderiam ser exibidos), não ^seguido de @, então você não pode simplesmente digitar ^e @em uma linha no comando acima.

Este comando remove todos os ^@.

phresus
fonte
4
Acabei de encontrar esta pergunta / resposta através de um link relacionado: Este é realmente um mau conselho e só funcionará corretamente em pouquíssimos casos. É melhor alterar a codificação, em vez de remover bytes nulos. Se você remover os bytes nulos, ainda poderá ter outros caracteres multibyte que aparecem como lixo.
7273 Mario
@ Mario, você poderia nos falar mais sobre a alteração na codificação? É algo relacionado à resposta do jrb abaixo?
George
Veja a resposta de rpyzh mais abaixo. Mostra o carregamento do arquivo usando a codificação adequada e o salvando com um código diferente (embora a resposta possa precisar de mais explicações). A última nota do Jrb é suficiente se você quiser apenas lê-la, mas não se quiser salvá-la sem os bytes nulos usando outra codificação.
Mario
50

Eu não acho que seus arquivos estão corrompidos. Sua linha de exemplo parece conter texto normal com bytes nulos entre cada caractere. Isso sugere que é um arquivo de texto codificado em UTF-16, mas a marca de ordem dos bytes está ausente desde o início do arquivo. Veja http://en.wikipedia.org/wiki/Byte-order_mark

Suponha que eu abra o Bloco de notas, digite a palavra 'nome do arquivo' e salve como Bigode end-Unicode. Um despejo hexadecimal desse arquivo se parece com o seguinte:

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

Se eu abrir esse arquivo no Vim, ele ficará bem - os bytes 'fe ff' informam ao Vim como o arquivo é codificado. Agora, suponha que eu crie um arquivo contendo exatamente a mesma sequência de bytes, mas sem o primeiro 'fe ff'. O Vim insere ^ @ (ou <00>, dependendo da sua configuração), no lugar dos bytes nulos; O bloco de notas insere espaços.

Portanto, em vez de remover os nulos, você deve realmente procurar que o Vim interprete o arquivo corretamente. Você pode fazer com que o Vim recarregue o arquivo com a codificação correta com o comando:

:e ++enc=utf16

jrb
fonte
Sim, o último comando feito no vim interpreta o arquivo corretamente, mas não remove os bytes nulos.
mrt181
6
Para removê-los, escolha outra codificação e salve o arquivo novamente:: set FENC = utf-8
Scy
35

Isso realmente funcionou para mim no vim:

:%s/\%x00//g
jriggins
fonte
5
isso funciona com substituto (), mas Ctl-VCtl-Shift-2 não.
precisa saber é o seguinte
Mesmo problema para mim, também não consegui trabalhar <Ctrl-V><Ctrl-2>(além da pessoa com <Ctrl-Shift-2>), mas isso funcionou.
31813 Jeff Bridgman
5
Isso funciona para mim linux. '00' é o valor ASCII hex, onde pode encontrar para qualquer personagem no vim, colocando o cursor sobre ele e digitando 'ga' (acho que "obter ascii) no modo de comando ou: como /:. Ascii na linha de comando vim .wikia.com / wiki /…
Casey Jones
^ Vx00 também funciona. Você também pode inserir o unicode de 16 bits com ^ VuXXXX. Eu tentei \% uXXXX em uma pesquisa e isso também funcionou.
Edward Falk,
Você será meu homem amado até o fim dos tempos. Do fundo do meu coração ... obrigado!
Gonzalo Cao
12

Esse 'símbolo' representa um caractere NULL, com valor ASCII 000.

É difícil remover com o vim, tente

tr -d '\000' < file1 > file2
pavium
fonte
7

Como outros observaram, esses são bytes nulos (ASCII 00). No Linux, a maneira de inserir valores ASCII no vim é pressionar Ctrl-V seguido pelo valor octal de 3 dígitos de qualquer caractere. Para substituir todos os bytes nulos, use:

    :%s/Ctrl-V000//g

(sem espaços).

Da mesma forma, você pode procurar nulos com:

    /Ctrl-V000

Nos dois casos, ele não mostrará os zeros enquanto você os digita, mas depois de inserir os três, será exibido ^@. Nos terminais coloridos, mostrará isso em azul para indicar que é um caractere de controle.

TheAmigo
fonte
6

FWIW, no meu caso, tive que usar o vim no cygwin para editar um arquivo de texto criado em um mac. A solução aceita não funcionou para mim, mas estava próxima. De acordo com a página wiki do Vim sobre como trabalhar com Unicode , há uma diferença entre as versões Big Endian e Little Endian do byte da BOM. Então, eu tive que dizer explicitamente vimpara usar uma versão Little Endian da codificação de BOM.

Somente depois de escolher a codificação correta, converti o formato do arquivo (finais de linha) para dosque eu pudesse editar o arquivo no editor do Windows. Tentar definir redefinir o formato do arquivo antes de especificar a codificação me deixou triste. Aqui está a lista completa de comandos que eu usei:

:e ++enc=utf16le
:w!
:e ++ff=mac
:setlocal ff=dos
:wq
rpyzh
fonte
Informações preciosas. No meu caso, era o endianness do byte da BOM.
Andre Albuquerque
3

A solução aceita não funcionou para mim. Eu fiz o vim canalizar o arquivo em trvez disso:

:%!tr -d '\000'

Isso também funcionaria bem com o modo visual (apenas digitar :!tr -d '\000') ou em várias linhas:

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

# Remove nulls from lines 3-5:
:3,5!tr -d '\000'
jnylen
fonte
2

^@ não é um caractere ruim se você usar uma codificação adequada, mas se desejar remover, tente:

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

^ O caractere M está presente nos dados de exemplo

Para converter seu arquivo para o formato Unix / Linux antes de qualquer processamento, tente:

dos2unix filename - rhel e outros

dos2ux filename [newfilename] - HP-UX

user490343
fonte
1

Além da resposta do @ jrb, no Vim, a codificação de caracteres do arquivo é detectada com base na opção codificação de arquivos. (observe os 's' no final das codificações de arquivo)

Ou seja, no Windows, o valor padrão para a fileencodingsopção é ucs-bom, o que significa:

verifique se a lista técnica existe no início do arquivo.

Se a lista técnica existir, 'leia a codificação de caracteres do arquivo fora da lista técnica'.

Se a BOM não existir (e, nesse caso, isso também significaria que todas as codificações de caracteres especificadas na fileencodingsopção falharam em corresponder), leia o arquivo com a codificação de caracteres especificada na encodingopção. A codificação de caracteres padrão para a encodingopção é: latin1. Agora, como latin1é a codificação de caracteres de um byte , todos os bytes no arquivo são latin1caracteres válidos (mesmo o Nulcaractere ^@que você está vendo *).

* - na verdade, ^@é o caractere de nova linha no texto do buffer do Vim, não o caractere Nul.

A maneira correta de ler o arquivo é especificar a codificação de caracteres manualmente como UTF-16 (pois parece que UTF-16 é a codificação char apropriada nesse caso).

colemik
fonte