【问题标题】:Perl - Regex - Group CapturingPerl - 正则表达式 - 组捕获
【发布时间】:2021-09-06 08:39:39
【问题描述】:

我在执行搜索并替换为捕获组时遇到了一些问题。

我正在创建 3 个组并尝试替换第一个和第三个,同时保持第二个不变。实际结果是正确替换了第 1 组和第 2 组的输出,而第 3 组没有被替换。

这是我尝试过的:

perl -p -e 's|(\x80\xbb)(.{4,})(\x00\x00\x00)|\xc6\x83$2\x00\x00\x01|g' "$1" > "$1.tmp"

输入:\x80\xbb`\xef\x00\x00\x00

预期:\xc6\x83`\xef\x00\x00\x01

我不是最擅长正则表达式,所以请帮帮我。我也愿意接受涉及 sed 的答案。

真实内容:

\x81\x00\x00\x00\x80\xbb`\xef\x00\x00\x00u!L\x89<$H\x8d\x15\x91\xec\x12\x00L\x89\xefL\x89\xf6H\x8bM\xc8L\x8bE\xd0M\x89

xxd:

0x000073ff  80bb 60ef 0000 0075 214c 893c 2448 8d15  ..`....u!L.<$H..                                                   
0x0000740f  91ec 1200 4c89 ef4c 89f6 488b 4dc8 4c8b  ....L..L..H.M.L.                                                   
0x0000741f  45d0 4d89 e1e8 5700 0000 c783 2c09 0000  E.M...W.....,...                                                   
0x0000742f  0000 0000 f20f 1005 652b 1200 0f29 8330  ........e+...).0                                                   
0x0000743f  0900 0048 b800 0000 0000 00f0 bf48 8983  ...H.........H..

编辑:我忘了说表示是十六进制的。

【问题讨论】:

  • 好的第一个 Q,因为您有样本输入、预期输出、当前输出和......喘气,一些代码!。我已经删除了 bash 标签,因为它不相关。 (可能也不是他的外壳标签;-/!)。继续发帖,祝你好运。
  • 不太好:显示的代码无法将给定的输入转换为所谓的实际输出。
  • 你用什么来生成“真实内容”?

标签: regex perl hex


【解决方案1】:

在代码中,您只保留两个连续字节进行替换,一个捕获组就足够了。

以下代码演示了如何将十六进制字符串转换为二进制值,进行所需的替换并将二进制输出为文本字符串。

use strict;
use warnings;
use feature 'say';

my($in,$out);

$out = $in = pack 'H*', '8100000080bb60ef00000075214c893c24488d1591ec12004c89ef4c89f648';
$out =~ s!\x80\xbb(.{2})\x00\x00\x00!\xc6\x83$1\x00\x00\x01!;

say 'in:  ' . unpack('H*',$in);
say 'out: ' . unpack('H*',$out);

输出

in:  8100000080bb60ef00000075214c893c24488d1591ec12004c89ef4c89f648
out: 81000000c68360ef00000175214c893c24488d1591ec12004c89ef4c89f648

【讨论】:

    【解决方案2】:

    我认为没有任何组被替换,至少在我尝试时。问题是.{4,},意思是“至少四个字符”,但只有两个:\x60\xef

    或者,如果您的输入确实是十六进制表示,请从代码中删除 \x:在双引号中,\x60 表示字符 `,而不是数字 60。它们由60 表示,没有任何前缀。

    #!/usr/bin/perl
    use warnings;
    use strict;
    use feature qw{ say };
    
    use Test::More;
    
    my $in = "\x80\xbb\x60\xef\x00\x00\x00";
    (my $out = $in) =~ s/(\x80\xbb)(.{2,})(\x00\x00\x00)/\xc6\x83$2\x00\x00\x01/g;
    is $out, "\xc6\x83\x60\xef\x00\x00\x01";
    
    my $in2 = '80bb60ef000000';
    (my $out2 = $in2) =~ s/(80bb)(.{4,})(000000)/c683${2}000001/g;
    is $out2, 'c68360ef000001';  #                   ~~~~
    

    注意${2}0 以防止将0 解释为变量名的一部分。

    【讨论】:

    • 谢谢@choroba。我已经运行了 perl 测试脚本并且它通过了。对2个字符的想法很好。出于某种原因,当我对文件执行正则表达式时,我没有得到相同的结果。有什么想法吗?
    • 检查十六进制转储中的文件内容,例如xxd.
    • 再次感谢@choroba。我将使用正确的更新输入。我非常抱歉。你能再看看更新的输入吗?非常感谢您的帮助。
    • 如果无法粘贴文件内容,请粘贴xxd 的实际输出。使用代码格式,这样空格就不会消失。
    • 可能需要/s,以防两个字节之一是0A
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    相关资源
    最近更新 更多