【问题标题】:Replace multiple hex values替换多个十六进制值
【发布时间】:2016-08-07 08:36:07
【问题描述】:

我编写了以下脚本,因为我需要对某些文件进行一些清理。我有特定数量的十六进制字符需要更改为另一组十六进制字符(即空到空格,见下文)。我写了下面的脚本,我的问题是它只替换了第一次出现,没有别的。

我已经尝试过 /g 就像常规的 sed 模式一样,但它不起作用。有没有办法做到这一点并替换所有匹配项?

(我没有使用$line =~ s/... 的原因是因为我认为它更整洁,更易于维护,并且有时可能需要编辑要替换的十六进制值的其他人需要访问和运行此脚本)。另一个原因是因为我需要将 10+ 十六进制值更改为等量的值,所以一个巨大的衬里将难以阅读。提前谢谢你。

 #!/usr/bin/perl


 use strict;
 use warnings;

 my $filebase = shift || "testreplace.txt";
 my $filefilter = shift || "testf";

 open my $fh1, '>', 'testreplaceout';

 # Iterate over file and read lines
 open my $file1, '<', $filebase;

 while (my $line = <$file1>)
 {
    chomp($line);

    for ($line) {
            s/\x00/\x20/g;
            s/\x31/\x32/g;
    }

    print {$fh1} "$line \n";


 }

【问题讨论】:

  • 我认为将一个字符替换为另一个字符时,tr 会更好(更快),即$line =~ tr/\x00/\x20/;(没有/g)。
  • 我要去试试,文件很大,所以我会比较时间告诉你!谢谢你的建议。我不记得了,但我认为 tr 也可以用一个特定的字符替换一系列字符,本着 tr /\x00-x20/\x20/;
  • tr 是个好建议。单个 tr 可以翻译任意数量的字符。例如tr/abc/xyz/ 会将 a 更改为 x,将 b 更改为 y,等等。

标签: perl file replace sed hex


【解决方案1】:

更新:阅读 cmets 了解此答案的注意事项。

这里有一种方法可以让您将正则表达式搜索/替换列表保持在脚本顶部,简洁明了,便于查看和修改:

use warnings;
use strict;

my @re_list = (
    ['a', 'x'],
    ['b', 'y'],
);

while (my $line = <DATA>){
    for my $re (@re_list){
        $line =~ s/$re->[0]/$re->[1]/g;
    }
    print $line;
}

__DATA__
aaabbbccc
bbbcccddd
ababababa

输出:

xxxyyyccc
yyycccddd
xyxyxyxyx

【讨论】:

  • 这种方式的问题是无法处理['a', 'x'], ['x', 'y']
【解决方案2】:

tr/// 可能是您最好的选择(因为您正在处理不断的单个字符替换)。以下是更通用的解决方案。

my %replacements = (
   'foo' => 'bar',
   'bar' => 'baz',
);

my $pat = join '|', map quotemeta, keys(%replacement);

s/($pat)/$replacements{$1}/g;

【讨论】:

    【解决方案3】:

    /g 会做你想做的事。如果它似乎不起作用,请添加一些调试:

    use Data::Dumper;
    $Data::Dumper::Useqq = $Data::Dumper::Terse = 1;
    

    在你的循环中:

    print Dumper($line);
    for ($line) {
            s/\x00/\x20/g;
            s/\x31/\x32/g;
    }
    print Dumper($line);
    

    将 tr 与成对的分隔符一起使用会非常易读/可维护:

    $line =~ tr[\x00\x31]
                      [\x20\x32];
    

    另外,考虑添加use autodie;

    【讨论】:

      猜你喜欢
      • 2018-07-16
      • 1970-01-01
      • 2020-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-05
      相关资源
      最近更新 更多