3

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

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

我记得曾经能够做到这一点,但只能使用 ??{},而且我现在手头没有代码。这可以在没有 ??{} (这是超级实验性的)的情况下使用较新的 5.10 捕获/反向引用之一来完成吗?

明显的表达不起作用:

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

2 回答 2

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

于 2012-03-16T10:13:00.310 回答
1

不,我认为不使用 是不可能的(??{ ... }),这将是:

/(\d++):((??{".{$^N}"}))/sg
于 2012-03-16T03:22:50.800 回答