perl - 多行匹配 perl 正则表达式

标签 perl

我有一个这样的文件:

01 00 01 14 c0 00 01 10 01 00 00 16 00 00 00 64
00 00 00 65 00 00 01 07 40 00 00 22 68 61 6c 2e
6f 70 65 6e 65 74 2e 63 6f 6d 3b 30 30 30 30 30
30 30 30 32 3b 30 00 00 00 00 01 08 40 00 00 1e
68 61 6c 2e 6f 70 65 6e 65 74 2d 74 65 6c 65 63
6f 6d 2e 6c 61 6e 00 00 00 00 01 28 40 00 00 21
72 65 61 6c 6d 31 2e 6f 70 65 6e 65 74 2d 74 65
6c 65 63 6f 6d 2e 6c 61 6e 00 00 00 00 00 01 25
40 00 00 1e 68 61 6c 2e 6f 70 65 6e 65 74 2d 74
65 6c 65 63 6f 6d 2e 6c 61 6e 00 00 00 00 01 1b
40 00 00 20 72 65 61 6c 6d 2e 6f 70 65 6e 65 74
2d 74 65 6c 65 63 6f 6d 2e 6c 61 6e 00 00 01 02
40 00 00 0c 01 00 00 16 00 00 01 a0 40 00 00 0c
00 00 00 01 00 00 01 9f 40 00 00 0c 00 00 00 00
00 00 01 16 40 00 00 0c 00 00 00 00 00 00 01 bb
40 00 00 28 00 00 01 c2 40 00 00 0c 00 00 00 00
00 00 01 bc 40 00 00 13 31 39 37 37 31 31 31 32
32 33 31 00

我正在阅读文件,然后找到某些八位字节并用标签替换它们:
while(<FH>){
    $line =~ s/(00 00 00 64)/<incr4>    /g;
    $line =~ s/(00 00 00 65)/<incr4>    /g;
    $line =~ s/(30 30 30 30 30 32)/<incr6ascii:999999:0>/g;
    $line =~ s/(31 31 32 32 33 31)/<incr6ascii:999999:0>/g;
    print OUTPUT $line;
}

例如,00 00 00 64将被 <incr4> 取代标签。这工作正常,但似乎无法再匹配多行了。例如模式 31 31 32 32 33 31运行在多行上,正则表达式似乎没有捕获它。我尝试使用/m/s 模式修饰符来忽略新行,但它们也不匹配。我能想出的唯一方法是使用以下方法将整个文件读入一个字符串:
undef $/;
my $whole_file = <FH>;
my $line = $whole_file;
$line =~ s/(00 00 00 64)/<incr4>    /g;
$line =~ s/(00 00 00 65)/<incr4>    /g;
$line =~ s/(30 30 30 30 30 32)/<incr6ascii:999999:0>/g;
$line =~ s/(31 31 32 32 33 31)/<incr6ascii:999999:0>/g;
print OUTPUT $line;

这是有效的,标签被正确插入,但文件的结构发生了根本性的改变。它全部都在一行上倾倒了。我想保留此处显示的文件结构。关于我如何做到这一点的任何想法?

/约翰

最佳答案

这里的技巧是匹配所有空格的类,如字符 \s :

my $file = do {local (@ARGV, $/) = 'filename.txt'; <>}; # slurp file

my %tr = (  # setup a translation table
    '00 00 00 64'       => '<incr4>',
    '00 00 00 65'       => '<incr4>',
    '00 30 30 30 30 32' => '<incr6ascii:999999:0>',
    '31 31 32 32 33 31' => '<incr6ascii:999999:0>',
);

for (keys %tr) {
    my $re = join '\s+' => split;  # construct new regex

    $file =~ s{($re)}{
       $1 =~ /\n/ ? "\n$tr{$_}" : $tr{$_}  # if octets contained \n, add \n
    }ge  # match multiple times, execute the replacement block as perl code
}
print $file;

关于perl - 多行匹配 perl 正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2852638/

相关文章:

unit-testing - 有没有办法在你的单元测试中覆盖 Perl "use constant"?

regex - 当我使用一字符长字符集时,为什么我的正则表达式不匹配?

perl - Perl 中的插入和取消移动有什么区别?

perl - 如何验证文件名?

jquery - 如何在 Perl 中访问通过 Ajax jquery 传递的数组

python - 哪种动态语言可以轻松使用其他语言的库?

perl - 如何使用 foreach 迭代数组而不更改循环变量的地址?

dbi - [perl]如何强制perl在我自己的路径中使用模块?

perl - 如何将自定义模块分发添加到本地 CPAN 镜像?

perl - 脚本 : Read condition written in words and converting into C - ternary operator