Делайте это с регулярным выражением с флагом /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. Даже если вы не используете модуль, вы можете посмотреть на их решение:)