在UNIX中识别和删除空字符

120

我有一个文本文件,其中包含不需要的空字符(ASCII NUL,\0)。当我尝试在 vi 中查看它时,我会看到插入在正常文本中的 ^@ 符号。如何:

  1. 确定文件中哪些行包含空字符?我尝试过使用 \0\x0 进行 grep,但这并没有起作用。

  2. 删除空字符?对该文件运行 strings 命令可以清除它,但我想知道这是否是最好的方式?


2
这种问题可能更适合SuperUser.com。 - Olivier Lalonde
2
实际上,这个问题在superuser.com上:http://superuser.com/questions/75130/how-to-remove-ths-symbol-with-vim - jrb
9个回答

152

我会使用 tr

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

如果你想知道在命令参数中间进行输入重定向是否可行,它是可以的。实际上,大多数Shell都可以识别和处理命令行中的I/O重定向(<、>等)。


12
我认为应该使用tr -d '\000' < file-with-nulls > file-without-nulls,因为<是shell管道功能的一部分,不是tr命令本身的功能。 - Mikael S
12
大多数 shell 命令都可以识别和处理参数字符串中的 < 或 > 符号。这个事实也让我感到惊讶。 - pra
1
使用输入重定向而不是 cat |,加一分。这是一个很好、干净的解决方案,解决了我的问题。 - Krzysztof Jabłoński
1
这对我来说比sed慢了一个数量级。 - diachedelic
4
在 POSIX opengroup tr 规范中,@Pointy 将 '\0' 替换为 '\000'。这是更好的选择原因。 - Harold Fischer
显示剩余12条评论

87

使用下面的sed命令来删除文件中的空字符。

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

这个解决方案直接在文件中进行编辑,如果文件仍在使用则很重要。传递参数-i'ext'会创建一个原始文件的备份,并添加后缀为“ext”。


7
注:在 FreeBSD(我相信也包括 Mac OS X)中,“sed -i” 需要在下一个参数中指定扩展名,但它可以为空。在这些系统中,添加'',如:sed -i'' 's/\x0//g "$FILE" - Tim Čas
3
对我来说,这比“tr”命令快了一个数量级。 - diachedelic
对于我来说,使用Git for Windows和$ sed --version-> sed(GNU sed)4.7,我必须使用以下调用才能获得一个名为example.csv.bak的备份文件:sed -i.bak 's/\x0//g' example.csv - Andrew Keeton
1
@TimČas,你做得很好,只是错过了一个单引号,应该是sed -i'' 's/\x0//g' some_file.xml。 - Dark
在 Mac 上,这只处理了第一个空字符而不是所有的空字符。gsed 可以处理所有的空字符。 - phyatt
sed -i '/\x0/d' null.txt 是一个有效的替代方案吗?也许更加优雅。 - Pablo Bianchi

23

大量不必要的 NUL 字符,比如每两个字节之间有一个,表明该文件采用 UTF-16 编码,应使用 iconv 将其转换为 UTF-8。


1
我的应用程序在记录日志时磁盘空间不足了,导致出现了这些字符。 - dogbane
例如,它可以使用以下命令运行:iconv -f UTF-16 -t UTF-8 file - djule5

10

我发现以下代码可以打印出哪些行包含空字符:

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

另外,八进制转储可以告诉您是否存在空值:

od file-with-nulls | grep ' 000'

6
如果文件中的行以 \r\n\000 结尾,那么需要删除 \n\000,然后将 \r 替换为 \n 才能正常处理。
tr -d '\n\000' <infile | tr '\r' '\n' >outfile

如果您发现自己在Windows DOS shell中,您可以从Sourceforge.net获取GNU/win32版本的Unix命令。我经常使用它们。请查看“od”命令,以分析文件中的内容... - wwmbes

3

2

我使用了:

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

去掉文件中的零。


0

使用PHP删除PDF文件末尾的空字符,与操作系统无关

该脚本使用PHP删除二进制文件末尾的空值,解决了由于空值触发的崩溃问题。您可以编辑此脚本以删除所有空字符,但是看一次如何完成此操作将有助于您理解其工作原理。

背景故事
我们从第三方接收PDF文件,需要使用PDF库将其上传到我们的系统中。在发送给我们的文件中,有时会附加一个空值到PDF文件末尾。当我们的系统处理这些文件时,具有末尾空值的文件会导致系统崩溃。

最初,我们使用sed,但是sed在Mac和Linux机器上的行为不同。我们需要一种平台无关的方法来提取末尾的空值。Php是最好的选择。而且,它是一个PHP应用程序,所以这很有意义 :)

此脚本执行以下操作:

将二进制文件转换为HEX(二进制文件不喜欢通过新行或回车符进行分割),使用回车符作为分隔符将字符串分割,如果值为空,则弹出数组的最后一个成员,使用回车符将数组合并,处理文件。

//In this case we are getting the file as a string from another application. 
// We use this line to get a sample bad file.
$fd = file_get_contents($filename);

//We trim leading and tailing whitespace and convert the string into hex
$bin2hex = trim(bin2hex($fd));

//We create an array using carriage return as the delminiter
$bin2hex_ex = explode('0d0a', $bin2hex);

//look at the last element.  if the last element is equal to 00 we pop it off
$end = end($bin2hex_ex);
if($end === '00') {
   array_pop($bin2hex_ex);
}

//we implode the array using carriage return as the glue
$bin2hex = implode('0d0a', $bin2hex_ex);

//the new string no longer has the null character at the EOF
$fd = hex2bin($bin2hex);

0

我遇到了相同的错误:

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

我通过将编码更改为utf-16来解决了这个问题。

f=cd.open(filePath,'r','utf-16')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接