Вот, пожалуйста.Протестировано на Perl v5.10 до v5.14.Ключом является рекурсивный шаблон , где мы применяем правило (?&Sequence)
.Это что-то вроде доказательства по индукции.
bigint
есть на тот случай, если вы действительно хотите сгенерировать последовательность из 1 .. 10**10_000
.Он будет работать значительно быстрее, если вы сможете ограничиться собственными машинными целочисленными значениями, 32-разрядными или 64-разрядными, в зависимости от вашей платформы.
#!/usr/bin/env perl
use v5.10;
use bigint; # only if you need stuff over maxint
my $pat = qr{
^
(?= 1 \b )
(?<Sequence>
(?<Number> \d+ )
(?:
\s+
(??{ "(?=" . (1 + $+{Number}) . ")" })
(?&Sequence)
)?
)
$
}x;
# first test embedded data
while (<DATA>) {
if ( /$pat/ ) {
print "PASS: ", $_;
} else {
print "FAIL: ", $_;
}
}
# now generate long sequences
for my $big ( 2, 10, 25, 100, 1000, 10_000, 100_000 ) {
my $str = q();
for (my $i = 1; $i <= $big; $i++) {
$str .= "$i ";
}
chop $str;
if ($str =~ $pat) {
print "PASS: ";
} else {
print "FAIL: ";
}
if (length($str) > 60) {
my $len = length($str);
my $first = substr($str, 0, 10);
my $last = substr($str, -10);
$str = $first . "[$len chars]" . $last;
}
say $str;
}
__END__
5
fred
1
1 2 3
1 3 2
1 2 3 4 5
1 2 3 4 6
2 3 4 6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
1 2 3 4 5 6 6
В результате выполнения:
FAIL: 5
FAIL: fred
PASS: 1
PASS: 1 2 3
FAIL: 1 3 2
PASS: 1 2 3 4 5
FAIL: 1 2 3 4 6
FAIL: 2 3 4 6
PASS: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
FAIL: 1 2 3 4 5 6 6
PASS: 1 2
PASS: 1 2 3 4 5 6 7 8 9 10
PASS: 1 2 3 4 5 [65 chars]2 23 24 25
PASS: 1 2 3 4 5 [291 chars] 98 99 100
PASS: 1 2 3 4 5 [3892 chars]8 999 1000
PASS: 1 2 3 4 5 [588894 chars]999 100000
Atриск казаться корыстным, есть книга , которая покрывает подобные вещи.См. Раздел «Необычные шаблоны» в главе 5 Программирование на Perl , издание 4ᵗʰ.Вы захотите проверить новые разделы «Именованные группы», «Рекурсивные паттерны» и «Грамматические паттерны».Книга находится в типографии и должна быть доступна в электронном виде через день или два.