Is there a way to break the regex into two or three regexes to fix this limit?
| [reply] |
c:\@Work\Perl\monks>perl -wMstrict -le
"my $s = join q{,}, 1 .. 40_000;
;;
$s =~ s{
\b (\d+) (?{ $1 }) \K
(?: , (\d+) \b (??{ ++$^R != $2 || length($1) != length($2) }))+
}{-$2}xmsg;
print qq{'$s'};
"
'1-9,10-99,100-999,1000-9999,10000-40000'
c:\@Work\Perl\monks>perl -wMstrict -le
"my $s = join q{,}, 1 .. 150_000;
;;
$s =~ s{
\b (\d+) (?{ $1 }) \K
(?: , (\d+) \b (??{ ++$^R != $2 || length($1) != length($2) }))+
}{-$2}xmsg;
print qq{'$s'};
"
Complex regular subexpression recursion limit (32766) exceeded at -e l
+ine 1.
Complex regular subexpression recursion limit (32766) exceeded at -e l
+ine 1.
Complex regular subexpression recursion limit (32766) exceeded at -e l
+ine 1.
'1-9,10-99,100-999,1000-9999,10000-42767,42768-75535,75536-99999,10000
+0-132767,132768-150000'
c:\@Work\Perl\monks>perl -wMstrict -le
"my $s = join q{,}, 1 .. 150_000;
;;
$s =~ s{
\b (\d+) (?{ $1 }) \K
(?:
(?: , (\d+) \b (??{ ++$^R != $2 || length($1) != length($2) })){1
+,30000}
)+
}{-$2}xmsg;
print qq{'$s'};
"
'1-9,10-99,100-999,1000-9999,10000-99999,100000-150000'
Updates:
- I should have mentioned that all these examples use the \K regex operator, so they all require Perl version 5.10 or greater.
- Changed last two code examples (increased range to 150,000) to make contrast greater.
- (2016/10/03) If you can stomach the \K operator (i.e., you're using Perl version 5.10+), here's a further tweak that speeds things up considerably. The critical enhancement is the use of the "(?(condition)yes-pattern)" conditional expression (see Extended Patterns in perlre). Some other changes have been made, but they seem immaterial to the speed-up. Old (slower) version:
c:\@Work\Perl\monks>perl -wMstrict -le
"use 5.010;
;;
print qq{perl version $]};
;;
my $s = join q{,}, 1 .. 1_500_000;
;;
my $end_point = qr{ , (\d++)
\b (??{ ++$^R != $2 || length($1) != length($2) })
}xms;
;;
my $start = time;
use re 'eval';
$s =~ s{
\b (\d++) (?{ $1 }) \K
(?: $end_point{1,32766})+
}{-$2}xmsg;
print qq{'$s'};
printf qq{in %d seconds \n}, time - $start;
"
perl version 5.010001
'1-9,10-99,100-999,1000-9999,10000-99999,100000-999999,1000000-1500000
+'
in 18 seconds
New (faster) version:
c:\@Work\Perl\monks>perl -wMstrict -le
"use 5.010;
;;
print qq{perl version $]};
;;
my $s = join q{,}, 1 .. 1_500_000;
;;
my $end_point = qr{ , (\d++)
(?(?{ ++$^R != $2 || length($1) != length($2) }) (*F))
}xms;
;;
my $start = time;
use re 'eval';
$s =~ s{
\b (\d++) (?{ $1 }) \K
(?: $end_point{1,32766})+
}{-$2}xmsg;
print qq{'$s'};
printf qq{in %d seconds \n}, time - $start;
"
perl version 5.010001
'1-9,10-99,100-999,1000-9999,10000-99999,100000-999999,1000000-1500000
+'
in 3 seconds
Give a man a fish: <%-{-{-{-<
| [reply] [d/l] [select] |