我有一个包含一些文件路径的二进制文件。如果路径以某个字符串开头,则应屏蔽文件路径[\x20-\x7f]+
的其余部分,保留文件的一般结构和大小!
因此,要搜索的路径列表是:
/usr/local/bin/
/home/joe/
然后在二进制数据中发生这样的事件:
^@^@^@^@/home/joe/documents/hello.docx^@^@^@^@
应改为:
^@^@^@^@/home/joe/********************^@^@^@^@
最好的方法是什么? sed,perl或awk有办法吗?或者我是否必须编写一个C或PHP程序,在其中找到字符串并在其位置写入strlen()
个掩码字符数?
答案 0 :(得分:3)
perl
是处理二进制数据的不错选择。对于sed
和awk
,只有GNU实现通常可以处理二进制数据,其他的会阻塞NUL字节或两个换行符之间的长序列或非终止行。 / p>
perl -pi.back -e 's{(/usr/local/bin|/home/joe)/\K[\x20-\x7f]+}{
$& =~ s/./*/rg}ge' binary-file
对于perl
标记,您需要/r
的版本不太旧(返回替换结果而不是将其应用于变量)和\K
(重置匹配字符串的开头。)
默认情况下,perl -p
一次只能处理一行,因为换行符不属于[\x20-\x7f]
,这很好。
答案 1 :(得分:0)
以下是一些有效的perl代码,但我确信它可以进行优化。它是一个过滤器,因此它将所有stdin读入$data
,然后对于数组@dirs
中的每个字符串,它会替换该模式。但是,替换不是固定字符串,而是函数调用replace($dir,$1)
,由于替换命令的e
修饰符而对其进行求值。
#!/usr/bin/perl
use strict;
sub replace{
my ($dir,$rest) = @_;
$rest =~ s/./*/g;
return $dir.$rest;
}
my @dirs = ('/usr/local/bin/','/home/joe/');
my $data = join("",<STDIN>);
foreach my $dir (@dirs){
$data =~ s|$dir([\x20-\x7f]+)|replace($dir,$1)|ge;
}
print $data;
该函数有2个参数,即模式的目录和捕获部分。它在替换捕获的字符串中的每个字符后返回这些连接。