如perlpacktut中所述,您可以使用X / Y *的解包字符串来首先获取字节流的长度,然后准确读取多个字节。但是,我正在努力在正则表达式中找到类似的东西,比如普通的ASCII数字和字符串。例如,Bencoded字符串的格式为:
[length]:[bytes]
4:spam
4:spam10:green eggs
我记得曾经能够将其关闭,但只能使用?? {},而且我现在没有方便的代码。这可以在没有?? {}(超级实验性)的情况下完成,使用较新的5.10捕获/反向引用吗?
明显的表达不起作用:
/(\d+)\:(.{\1})/g
/(\d+)\:(.{\g-1})/g
答案 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