我有这个数据文件,它应该是一个普通的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+$//
替换数组成员。那个垃圾究竟是什么?不幸的是,我无法控制数据,这是第三方数据。
有什么想法吗?
答案 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");