2012-03-16 77 views
3

正如perlpacktut中详细描述的那样,您可以使用解压字符串X/Y *先获取字节流的长度,然后读取正是那么多字节。但是,我正努力在正则表达式中找到类似这样的东西,例如纯ASCII数字和字符串。例如,一个B编码字符串的形式:正则表达式中的Perl的解压缩(“A4/A *”)长度+字节语法

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

我记得有一次能拉这一关,但仅在使用?? {},我没有代码,方便好用现在。这可以不使用?? {}(这是超级实验)来完成,使用新的5.10捕获/反向引用之一?

明显的表达不工作:

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

这可能是一种情况,只需编写一个小函数而不使用正则表达式是最有效的方法。 – huon 2012-03-16 02:24:26

+1

我想用一个正则表达式来查找长度,然后用'@ +'和'substr'来提取文本,如果我想继续搜索,则分配给'pos'。 – cjm 2012-03-16 03:18:53

回答

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。即使你不使用模块,你也可以看看他们的解决方案:)

+0

哦,我知道,但我想创建一个基于来自Convert :: Bencode的代码并将其用于Encode :: Encoding基础的Encode :: Bencode模块。但是,由于输出对象的性质(不是流数据),我不确定这种事情是否适用。 – 2012-03-25 14:49:31

1

不,我不认为这是可能的,而无需使用(??{ ... }),具体做法是:

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