【问题标题】:Perl beginner: How can I find/replace ascii characters in a file?Perl 初学者:如何在文件中查找/替换 ascii 字符?
【发布时间】:2013-08-19 15:39:57
【问题描述】:

我对 Perl 完全陌生,我认为这是解决我的简单任务的最佳语言。我需要将二进制文件转换为可读的文件,并且需要查找并将\x00\x39 之类的字符串替换为\x09(制表符)或类似的东西。

我从 bash 开始,效果很好:

perl -pi -e 's/abc/123/g' test.txt

但是,当我开始输入 ascii 代码时,我迷路了:

perl -pi -e 's/0x49/*/g' test.txt
perl -pi -e 's/{char(49)}/*/g' test.txt

这个命令在 perl 脚本中会是什么样子?我有大约几百个这样的查找/替换操作和一个 500MB 的文本文件。有什么需要我知道的警告吗?

非常感谢您的帮助!

加里

【问题讨论】:

    标签: perl replace find ascii


    【解决方案1】:

    使用\x## 表示法:

    perl -pi~ -e 's/\x00/*/g' test.txt
    

    要将每个“特殊”字符替换为其括号中的代码,请使用/e 选项:

    perl -pi~ -e 's/([\x0-\x09\x11-\x1f])/"[" . ord($1) . "]"/eg' test.txt
    

    【讨论】:

    • 是的,这就是我需要的;我错过了反斜杠:-)
    【解决方案2】:

    哇,非常感谢。我了解到这并不像我想象的那么容易。哇,Perl 真的很复杂 ;-)

    这就是我想出的。我希望这会对某人有所帮助。

    顺便说一句:如果您有机会知道这是否也适用于 Windows Perl,请告诉我。

    再次感谢,

    加里

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    my $infile = '/Users/gc/Desktop/a.bin'; 
    my $outfile = '/Users/gc/Desktop/b.txt';    # in and out can be the same file; file will be overwritten when it already exists
    
    my $data = read_file($infile);
    
    # 1st batch
    $data =~ s/0\x01J[\x00-\x19]/\x09AnythingYouWant\x09/g;
    $data =~ s/0\x00[\x00-\x19]/\x09AnythingYouWant\x09/g;
    
    # 2nd batch
    $data =~ s/\r/\x06/g;                                   # CR into \x06
    $data =~ s/\n/\x06/g;                                   # LF into \x06
    $data =~ s/\r\n/\x06/g;                                 # CR LF into \x06
    
    # …
    
    write_file($outfile, $data);
    exit;
    
    sub read_file {
        my ($infile) = @_;
    
        open my $in, '<', $infile or die "Could not open '$infile' for reading $!";
        local $/ = undef;
        my $all = <$in>;
        close $in;
    
        return $all;
    }
    
    sub write_file {
        my ($outfile, $content) = @_;
    
        open my $out, '>', $outfile or die "Could not open '$outfile' for writing $!";;
        print $out $content;
        close $out;
    
        return;
    }
    

    【讨论】:

      【解决方案3】:

      虽然在二进制文件上进行字符串替换有点奇怪,但这里是如何用你的 txt 文件来做的:

      use strict;
      use warnings;
      use Tie::File;
      
      my @file;
      tie @file, 'Tie::File', 'test.txt' or die $!;
      
      foreach (@file) {
        # your regexes go here
        s/abc/123/g;
        s/\0x49/*/g;
      }
      
      untie @file;
      

      Tie::File module(来自 Perl 核心)允许您通过数组访问文件的行。更改将立即保存到文件中。在foreach 循环中,文件被逐行处理。这些行进入$_,我们看不到。正则表达式操作默认也适用于$_,所以不需要写下来。


      但是,我相信您的做法是错误的。在大多数情况下,您将无法逐行读取文件。请参考perlfaq 作为起点。恐怕处理二进制比文本处理要复杂一些。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-27
        • 2012-07-03
        • 1970-01-01
        • 2012-06-23
        • 2014-04-08
        • 1970-01-01
        • 2013-11-28
        • 1970-01-01
        相关资源
        最近更新 更多