I prefer a line-by-line approach and create a new array each time a line starting with a number is encountered. I assume that the data fits into memory, otherwise sorting will be difficult:
use strict;
use warnings;
my @lines;
while(<DATA>){
push @lines, [$1] if /^(\d+)/;
push @{$lines[-1]}, $_;
}
print @$_[1..@$_-1] for sort { $a->[0] <=> $b->[0] } @lines;
__DATA__
2 [...]
[line1]
[line2]
[line3]
3 [...]
[line1]
1 [...]
[line1]
[line2]
2 [...]
[line1]
[line2]
Update:
@lines should really be called
@blocks