如何从二进制垃圾中清理数据文件?

时间:2011-06-10 14:36:38

标签: linux perl file binary

我有这个数据文件,它应该是一个普通的ASCII文件。但是,它在第​​一行的末尾有一些垃圾。它只显示我用vi或更少的时间看它 - >

  y mon d  h XX11 XX22 XX33 XX44 XX55 XX66^@
2011  6 6 10 14.0 15.5 14.3 11.3 16.2 16.1

grep也说这是一个二进制文件:Binary file data.dat matches

这在我的解析脚本中造成了一些麻烦。我正在拆分每一行并将它们放到数组中。第一个数组中的最后一个元素(XX66)以某种方式被破坏,因为垃圾而且我无法匹配它。

如何清理那条线或阵列?我已经尝试dos2unix到文件并用s/\s+$//替换数组成员。那个垃圾究竟是什么?不幸的是,我无法控制数据,这是第三方数据。

有什么想法吗?

4 个答案:

答案 0 :(得分:1)

Grep试图变得聪明,当它看到一个不可打印的字符时,切换到“二进制”模式。添加“-a”或“--text”以强制grep保持“文本”模式。

对于sed,请尝试sed -e 's/\([^ -~]*\)//g',其中说“将 space tilde 之间的所有内容(分别为字符0x20和0x7E)更改为” 。这也会剥离标签,但你可以在空格之前插入一个标签字符以包含它们(或任何其他特殊字符)。

“^ @”是表示NUL(又名“ascii(0)”或“\ 0”)的一种方式。如果某些程序以天真的方式实现,它们也可能会将其视为文件结尾。

答案 1 :(得分:0)

如果它总是相同的代码(例如^ @或相关的),那么你可以找到/替换它们。

以Vim为例:

编辑模式下的

:%s/^@//g将清除任何这些字符。

要输入^@等字符,请按住Ctrl键,然后按“v”然后按下您需要的字符 - 在上述情况下,请记住按住shift键以获取@键。应按住Ctrl键直到结束。

答案 2 :(得分:0)

^ @看起来像是一个控制角色。我无法弄清楚应该是什么角色,但我想这并不重要。

你可以使用s / ^ @ // g来摆脱它们,但你必须实际复制角色,只需将^和@放在一起就不会这样做。

E:F; B'/ P>

答案 3 :(得分:0)

我创建了这个小脚本来删除文件中的所有二进制,非ASCII和一些恼人的字符。请注意,char是基于八进制的:

#!/usr/bin/perl
use strict;
use warnings;

my $filename = $ARGV[0];
open my $fh, '<', $filename or die "File not found: $!";
open my $fh2, '>', 'report.txt' ;
binmode($fh);

my ($xdr, $buffer) = "";

# read 1 byte at a time until end of file ...
while (read ($fh, $buffer, 1) != 0) {   
    # append the buffer value to xdr variable
    $xdr .= $buffer; 
    if (!($xdr =~ /[\0-\11]/) and (!($xdr =~ /[\13-\14]/))and (!($xdr =~ /[\16-\37]/)) and (!($xdr =~ /[\41-\55]/)) and (!($xdr =~ /[\176-\177]/))) {
        print $fh2 $xdr;
    }
    $xdr = "";
} 
# finaly, clean all the characters that are not ASCII.
system("perl -plne 's/[^[:ascii:]]//g' report.txt > $filename.clean.txt");