Как убрать этот символ "^ @" с vim?

58104
mrt181

У меня есть некоторые файлы, которые повреждены этим символом:

^ @

Это не часть строки; это не для поиска. Как заменить этот символ ничем или как удалить этот символ?

Вот пример строки из одного файла:

^@F^@i^@l^@e^@n^@a^@m^@e^@ ^@ ^@ ^@ ^@ ^@ ^@ ^@ ^@ ^@ ^@:^@ ^@^M^@ 
50

9 ответов на вопрос

46
jrb

Я не думаю, что ваши файлы повреждены. Ваша строка примера выглядит так, как будто она содержит обычный текст с нулевыми байтами между каждым символом. Это говорит о том, что это текстовый файл, который был закодирован в UTF-16, но в начале файла отсутствует метка порядка байтов. Смотрите http://en.wikipedia.org/wiki/Byte-order_mark

Предположим, я открываю Блокнот, набираю слово «имя файла» и сохраняю как Unicode Big-endian. Шестнадцатеричный дамп этого файла выглядит так:

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

Если я открою этот файл в Vim, он выглядит нормально - байты 'fe ff' сообщают Vim, как кодируется файл. Теперь предположим, что я создаю файл, содержащий точно такую ​​же последовательность байтов, но без начального 'fe ff'. Vim вставляет ^ @ (или <00>, в зависимости от вашей конфигурации) вместо нулевых байтов; Блокнот вставляет пробелы.

Поэтому вместо того, чтобы удалять нули, вам действительно нужно, чтобы Vim правильно интерпретировал файл. Вы можете заставить Vim перезагрузить файл с правильной кодировкой с помощью команды:

:e ++enc=utf16

Да, последняя команда заставила vim правильно интерпретировать файл, но не удаляет нуль-байты. mrt181 14 лет назад 0
Чтобы удалить их, выберите другую кодировку и снова сохраните файл:: set fenc = utf-8 scy 13 лет назад 6
46
phresus

Вы можете попробовать:

  • %s/<CTRL-2>//g (на обычных ПК)

  • %s/<CTRL-SHIFT-2>//g (на компьютерах Mac)

где <CTRL-2>означает сначала нажать CTRLна обычных ПК, удерживая его нажатым, ударить 2, отпустить CTRL.

и <CTRL-SHIFT-2>означает сначала нажать controlна ПК Mac, удерживая его нажатым, нажать shiftна ПК Mac, удерживая его нажатым, нажать 2, отпустить controlи shift.

Наконец, обе команды должны появиться %s/^@//gна экране. ^@означает один символ (байт NULL, который иначе не может быть отображен), ^за которым не следует @, поэтому вы не можете просто набрать ^и @в строке в приведенной выше команде.

Эта команда удаляет все ^@.

это удаляет нуль-байты, спасибо mrt181 14 лет назад 2
Просто наткнулся на этот вопрос / ответ по соответствующей ссылке: На самом деле это плохой совет, и он будет работать должным образом только в очень немногих случаях. Лучше на самом деле изменить кодировку, чем удалять нулевые байты. Если вы удалите нулевые байты, у вас могут остаться другие многобайтовые символы, которые отображаются как мусор. Mario 10 лет назад 3
@ Марио, не могли бы вы рассказать нам больше об изменении кодировки? Это как-то связано с ответом JRB ниже? George 10 лет назад 0
Смотрите ответ РПыж ниже. Показывает загрузку файла с использованием правильной кодировки, а также сохранение его с другой (хотя для ответа может потребоваться более подробное объяснение). Последнее примечание Jrb достаточно, если вы просто хотите прочитать его, но не если вы хотите сохранить его без нулевых байтов, используя другую кодировку. Mario 10 лет назад 0
28
jriggins

Это на самом деле работает для меня в VIM:

:%s/\%x00//g 
это работает с substitute (), а Ctl-VCtl-Shift-2 - нет. dsummersl 11 лет назад 4
Та же проблема для меня, я не мог получить`(также как и с``) работать тоже, но это сработало. Jeff Bridgman 10 лет назад 0
Это работает для меня Linux. '00' - это шестнадцатеричное значение ASCII, которое вы можете найти для любого символа в vim, поместив курсор над ним и введя 'ga' (think "get ascii) в командном режиме или: as /: ascii в командной строке. Http : //vim.wikia.com/wiki/Showing_the_ASCII_value_of_the_current_character Casey Jones 9 лет назад 3
^ Vx00 тоже работает. Вы также можете ввести 16-битный юникод с помощью ^ VuXXXX. Я попытался \% uXXXX в поиске, и это тоже сработало. Edward Falk 7 лет назад 0
11
pavium

Этот символ представляет символ NULL со значением ASCII 000.

С vim удалить сложно, попробуйте

tr -d '\000' < file1 > file2 
6
rpyzh

FWIW, in my case I had to use vim on cygwin to edit a text file created on a mac. The accepted solution didn't work for me, but was close. According to Vim wiki page about working with Unicode, there is a difference between Big Endian and Little Endian versions of the BOM byte. So, I had to explicitly tell vim to use a Little Endian version of BOM encoding.

Only after picking the right encoding I converted the file format (line endings) to dos so I could edit the file in Windows editor. Trying to set reset the file format before specifying the encoding gave me grief. Here is the full list of commands I used:

:e ++enc=utf16le :w! :e ++ff=mac :setlocal ff=dos :wq 
Ценная информация. В моем случае это был порядок байтов спецификации. Andre Albuquerque 10 лет назад 0
5
TheAmigo

Как отметили другие, это нулевые байты (ASCII 00). В Linux способ ввода значений ASCII в vim - это нажать Ctrl-V, а затем восьмеричное восьмеричное значение любого символа. Чтобы заменить все нулевые байты, используйте:

    :%s/Ctrl-V000//g

(без пробелов).

Аналогично, вы можете искать нули с помощью:

    /Ctrl-V000

В обоих случаях нули не будут отображаться при вводе, но после ввода всех трех будут отображаться ^@. На цветных терминалах это будет отображаться синим цветом для обозначения контрольного символа.

3
jnylen

Принятое решение не сработало для меня. Я сделал VIM трубу через файл tr:

:%!tr -d '\000' 

Это также будет хорошо работать с визуальным режимом (просто печатать :!tr -d '\000') или с рядом строк:

# Remove nulls from current line: :.!tr -d '\000'  # Remove nulls from lines 3-5: :3,5!tr -d '\000' 
2
user490343

^@ Неплохой символ, если вы используете правильную кодировку, но если вы хотите удалить, попробуйте:

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

Символ ^ M есть в данных вашего примера

Чтобы преобразовать ваш файл в формат Unix / Linux перед любой обработкой, попробуйте:

dos2unix filename - Рел и другие

dos2ux filename [newfilename] - HP-UX

1
colemik

В дополнение к ответу @ jrb, в Vim определяется кодировка символов файла на основе опции fileencodings. (обратите внимание на 's' в конце кодирования файла)

Т.е. в Windows значением по умолчанию для этой fileencodingsопции является ucs-bom:

проверьте, существует ли спецификация в начале файла.

Если спецификация существует, тогда «прочитайте кодировку символов файла из спецификации».

Если спецификация не существует (и в этом случае это также означает, что все кодировки символов, указанные в fileencodingsпараметре, не совпадают), тогда прочитайте файл с кодировкой символов, указанной в encodingпараметре. Кодировка символов по умолчанию для encodingопции: latin1. Теперь, поскольку latin1это кодировка символов длиной в один байт, все байты в файле являются допустимыми latin1символами (даже Nulсимвол, ^@который вы видите *).

* - фактически, ^@это символ новой строки в тексте буфера Vim, а не символ Nul.

Правильный способ чтения файла - указать кодировку символов вручную как UTF-16 (в этом случае UTF-16 выглядит как правильная кодировка символов).

Похожие вопросы