Perl以正则表达式形式解压缩(“A4 / A *”)长度+字节语法

时间:2012-03-16 01:53:19

标签: regex perl unpack backreference string-length

如perlpacktut中所述,您可以使用X / Y *的解包字符串来首先获取字节流的长度,然后准确读取多个字节。但是,我正在努力在正则表达式中找到类似的东西,比如普通的ASCII数字和字符串。例如,Bencoded字符串的格式为:

[length]:[bytes]
4:spam
4:spam10:green eggs

我记得曾经能够将其关闭,但只能使用?? {},而且我现在没有方便的代码。这可以在没有?? {}(超级实验性)的情况下完成,使用较新的5.10捕获/反向引用吗?

明显的表达不起作用:

/(\d+)\:(.{\1})/g
/(\d+)\:(.{\g-1})/g

2 个答案:

答案 0 :(得分:3)

使用带有/g标志和\G锚点的正则表达式,但在标量上下文中。这样可以在最后一个模式匹配(或第一个模式的开头)之后保持字符串中的位置。你可以这样沿着弦走。获取长度,跳过冒号,然后使用substr来获取正确数量的字符。您实际上可以分配给pos,因此请为刚刚提取的字符更新它。 redo直到你没有更多匹配:

use v5.10.1;

LINE: while( my $line = <DATA> ) {
    chomp( $line );
    {
    say $line;
    next LINE unless $line =~ m/\G(\d+):/g;  # scalar /g!
    say "\t1. pos is ", pos($line); 
    my( $length, $string ) = ( $1, substr $line, pos($line), $1 );
    pos($line) += $length; 
    say "\t2. pos is ", pos($line); 
    print "\tFound length $length with [$string]\n";
    redo;
    }
    }

__END__
4:spam6:Roscoe
6:Buster10:green eggs
4:abcd5:123:44:Mimi

注意最后一个输入行的边缘情况。 3:是字符串的一部分,而不是新记录。我的输出是:

4:spam6:Roscoe
    1. pos is 2
    2. pos is 6
    Found length 4 with [spam]
4:spam6:Roscoe
    1. pos is 8
    2. pos is 14
    Found length 6 with [Roscoe]
4:spam6:Roscoe
6:Buster10:green eggs
    1. pos is 2
    2. pos is 8
    Found length 6 with [Buster]
6:Buster10:green eggs
    1. pos is 11
    2. pos is 21
    Found length 10 with [green eggs]
6:Buster10:green eggs
4:abcd5:123:44:Mimi
    1. pos is 2
    2. pos is 6
    Found length 4 with [abcd]
4:abcd5:123:44:Mimi
    1. pos is 8
    2. pos is 13
    Found length 5 with [123:4]
4:abcd5:123:44:Mimi
    1. pos is 15
    2. pos is 19
    Found length 4 with [Mimi]
4:abcd5:123:44:Mimi

我认为可能有一个模块,有:Bencode。它做我做的。这意味着我做了很多工作。始终先看看CPAN。即使您不使用该模块,您也可以查看他们的解决方案:)

答案 1 :(得分:1)

不,我不认为如果不使用(??{ ... })就可以实现:

/(\d++):((??{".{$^N}"}))/sg