我正在使用binmode()块读取文件,并希望删除与静态列表中任何值匹配的字节值。
@strip = (91, 92, 98, 107, 5, 64, 21, 13, 11, 12)我在我的剧本里做什么
binmode($fh);
read($fh,$data,20);
%strip = (91=>1, 92=>1,98=>1,107=>1,5=>1,64=>1,21=>,13=>1,11=>1,12=>1);
$data=~s/(.)/$strip{ord($1)} ? "" :$1/ge恐怕,这样做可能是不正确的,并有一些不良的结果。
有人能提出更清洁有效的替代方法来实现这一目标吗?
发布于 2019-03-26 19:24:10
regex引擎非常乐意在字节字符串上操作(尽管使用\d之类的操作可能没有任何意义),所以您的方法是非常好的。但是白色很有效率,它可以加速。
如果我们在字节上使用chr来剥离,而不是在读取的所有字符上使用ord呢?
my @to_strip = ( 5, 11, 12, 13, 21, 64, 91, 92, 98, 107 );
my %to_strip = map { chr($_) => 1 } @to_strip;
$data =~ s/(.)/ $strip{$1} ? "" :$1 /ge;如果我们再往前走一步,更早地做出替代选择呢?
my @to_strip = ( 5, 11, 12, 13, 21, 64, 91, 92, 98, 107 );
my %to_strip = map { chr($_) => 1 } @to_strip;
my %map = map { $to_strip{$_} ? "" : $_ } map chr, 0x00..0xFF;
$data =~ s/(.)/$map{$1}/sg;但我们仍在做很多不必要的替换工作。如果我们搜索要替换的特定字符,该怎么办?
my @to_strip = ( 5, 11, 12, 13, 21, 64, 91, 92, 98, 107 );
my $pat = "[" . quotemeta( pack( 'C*', @to_strip ) ) . "]+";
my $re = qr/$pat/;
$data =~ s/$re//g;这个速度要快得多,原因有三个:
请记住,@to_strip、%to_strip、%map、$pat和$re只需要计算一次,而不是每read计算一次。当我谈到上面提到的速度时,我并没有包括计算这些数据所需的时间,因为我假设您将进行多次读取和替换。
也就是说,如果硬编码要删除的字节是合理的,tr///d将为您提供最佳性能。
$data =~ tr/\x05\x0B-\x0D\x15\x40\x5B\x5C\x62\x6B//d;从动态列表中使用tr///并不有效,因为tr///不插值。我们不得不建造一艘潜艇,而调用潜艇的速度相对较慢。
my @to_strip = ( 5, 11, 12, 13, 21, 64, 91, 92, 98, 107 );
my $class = quotemeta( pack( 'C*', @to_strip ) );
my $inline_stripper = eval("sub { $_[0] =~ tr/$class//d; }");
$inline_stripper->($data);以下是一种有效的(但肯定不是那么有效的)非正则表达式方法。
my @to_strip = ( 5, 11, 12, 13, 21, 64, 91, 92, 98, 107 );
my @to_strip_lookup; $to_strip_lookup[$_] = 1 for @to_strip;
$data = pack 'C*', grep !$to_strip_lookup[$_], unpack 'C*', $datahttps://stackoverflow.com/questions/55364557
复制相似问题