如何用vim删除符号“ ^ @”?


59

我有一些文件用此符号损坏:

^ @

它不是字符串的一部分;它是不可搜索的。如何用任何符号代替该符号,或者如何删除该符号?

这是来自一个文件的示例行:

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

Answers:


51

您可以尝试:

  • %s/<CTRL-2>//g (在普通PC上)

  • %s/<CTRL-SHIFT-2>//g (在Mac PC上)

此处的<CTRL-2>意思是先按下CTRL常规PC上的,并保持按下,击打2和释放的状态CTRL

<CTRL-SHIFT-2>意味着先按下controlMac PC上的,保持按下状态,再按下shiftMac PC上的,保持按下状态,按下2,释放controlshift

最后,这两个命令都应显示在%s/^@//g屏幕上。^@表示一个字符(一个NULL字节,否则将无法显示),而不是^后跟@,因此您不能仅在上述命令中键入^@一行。

此命令将删除所有^@


4
只是通过一个相关链接偶然发现了这个问题/答案:这实际上是一个糟糕的建议,仅在极少数情况下才能正常工作。实际更改编码比删除空字节更好。如果删除空字节,则可能还会有其他多字节字符显示为垃圾。
Mario

@Mario您能告诉我们更多有关编码更改的信息吗?它与下面的jrb答案有关吗?
乔治

请在下面进一步查看rpyzh的答案。显示使用正确的编码加载文件以及将其保存为其他编码(尽管答案可能需要更多说明)。如果您只想阅读Jrb的最后一个音符就足够了,但是如果您想使用其他编码将其保存为不包含空字节的话,则不够。
马里奥(Mario)

50

我不认为您的文件已损坏。您的示例行看起来像包含常规文本,每个字符之间都有空字节。这表明它是一个以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

6
要删除它们,选择其他的编码再保存文件:设置FENC = UTF-8
SCY

35

这实际上在vim中对我有用:

:%s/\%x00//g

5
这适用于replace(),但Ctl-VCtl-Shift-2无效。
dsummersl

对我来说,同样的问题,我也无法<Ctrl-V><Ctrl-2>(以及使用的人<Ctrl-Shift-2>)工作,但这确实可行。
Jeff Bridgman 2013年

5
这适用于我的Linux。“00”是ASCII十六进制值,您可以通过将光标放在它并输入“嘎”找到vim的任何字符(认为“得到ASCII)在命令模式或:如/:在命令行上ASCII VIM .wikia.com / wiki /…
凯西·琼斯

^ Vx00也可以。您也可以使用^ VuXXXX输入16位unicode。我在搜索中尝试了\%uXXXX,这也有效。
爱德华·福尔克

直到时间的尽头,您将成为我的挚爱。从我的内心深处...谢谢你!
贡萨洛·曹

12

该“符号”代表NULL字符,ASCII值000。

用vim很难删除,尝试

tr -d '\000' < file1 > file2

7

正如其他人指出的那样,这些是空字节(ASCII 00)。在Linux上,将ASCII值输入vim的方法是按Ctrl-V,然后按任意字符的3位八进制值。要替换所有空字节,请使用:

    :%s/Ctrl-V000//g

(无空格)。

同样,您可以使用以下命令搜索空值:

    /Ctrl-V000

在这两种情况下,键入时都不会显示零,但是在输入所有三个后,将显示^@。在彩色端子上,它将以蓝色显示,表示它是控制字符。


6

FWIW,就我而言,我必须在cygwin上使用vim编辑在Mac上创建的文本文件。可接受的解决方案对我不起作用,但是很接近。根据Vim Wiki页面上有关使用Unicode的信息,BOM字节的Big Endian版本和Little Endian版本之间存在差异。因此,我必须明确告知vim要使用Little Endian版本的BOM编码。

仅在选择了正确的编码后,我才将文件格式(行尾)转换为,dos以便可以在Windows编辑器中编辑文件。在指定编码之前尝试设置重设文件格式让我很伤心。这是我使用的命令的完整列表:

:e ++enc=utf16le
:w!
:e ++ff=mac
:setlocal ff=dos
:wq

宝贵的信息。在我的情况下,这是BOM字节的字节序。
Andre Albuquerque 2014年

3

接受的解决方案对我不起作用。我用vim通过管道传递文件tr

:%!tr -d '\000'

这在可视模式(只是type :!tr -d '\000')或一系列行上也可以很好地工作:

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

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

2

^@ 如果使用正确的编码,则不是一个坏字符,但是如果要删除,请尝试:

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

您的示例数据中有^ M个字符

要在进行任何处理之前将文件转换为Unix / Linux格式,请尝试:

dos2unix filename -Rhel和其他

dos2ux filename [newfilename] -HP-UX


1

除了@jrb的答案外,在Vim中,还将根据fileencodings选项检测文件的字符编码。(请注意文件编码末尾的“ s”)

即在Windows上,该fileencodings选项的默认值为ucs-bom,表示:

检查BOM表是否存在于文件的开头。

如果存在BOM,则“从BOM中读取文件的字符编码”。

如果BOM不存在(在这种情况下,这也意味着该fileencodings选项中指定的所有字符编码均不匹配),请使用该encoding选项中指定的字符编码读取文件。该encoding选项的默认字符编码为:latin1。现在,由于latin1一字节长的字符编码,因此文件中的所有字节都是有效latin1字符(甚至是您看到的Nul字符^@*)。

*-实际上^@是Vim缓冲区文本中的换行符,而不是Nul字符。

读取文件的正确方法是手动将字符编码指定为UTF-16(因为在这种情况下,看起来UTF-16是正确的char编码)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.