#! perl -slw use strict; package GenURLs; #! Generals:) use Carp; use Data::Dumper; my $re = qr/^(.*?)([[{])([^]}]+)([]}])(.*?)$/; my ($base, @ranges); sub new { my ($class, $template) = (@_); croak "Usage: my \$obj = new GenURLs 'template[1-10]/{a,b,c}[-1-+1]'" unless $template and $template =~ $re; my $i = 0; while( $template =~ s/$re/$1\cA$i\cA$5/g ) { croak "Bad template: '$template' $1, $2, $3, $4, $5" unless defined $4 and 1+index( '[]{}', "$2$4"); if ( $2 eq '[' ) { my $range = $3; my ($start, $stop) = $range =~ /(\d+)-(\d+)/; croak "Bad range: [$start-$stop]" unless $start < $stop; push @ranges, {type=>'RANGE', start=>$start, stop=>$stop}; } else { my @list= split',', $3; push @ranges, {type=>'LIST', last=>,0, values=>\@list }; } $i++; } $base = $template; # print "$base\n", Dumper( \@ranges); return bless [], $class; } sub getIterator { my ($self, $nBatch) = @_; my $state = {last=>$base, batch=>$nBatch, nextIdx=>$#ranges, ranges=>$#ranges }; return sub { my ($count, @list) = ($state->{nBatch}, ()); my $range = $state->{nextRange} || $state->{ranges}; do { incrRange( $state, $range ); (my $item = $state->{last}) =~ tr/\cA//d; print "Pushing : '$item'"; push(@list, $item); } while (--$count and $range >=0); $state->{nextRange} = $range if $range >=0; return @list; }; } sub incrRange { my ($state, $range) = @_; my $carry = 0; if ($ranges[$range]{type} eq 'RANGE') { $state->{last} =~ s[((?:\cA(?:[^\cA]+)\cA){$range})(?:\cA([^\cA]+)\cA)] [ my $val = $2 + 1; if ($val >= $ranges[$range]{stop}) { $val = $ranges[$range]{start}; $carry = 1; } "$1\cA$val\cA"; ]e; } else { $state->{last} =~ s[((?:\cA(?:[^\cA]+)\cA){$range})(?:\cA([^\cA]+)\cA)] [ my $iVal = $ranges[$range]{last}++; if ($iVal > $#{$ranges[$range]{values}}) { $iVal = $ranges[$range]{last} = 0; $carry = 1; } "$1\cA@{$ranges[$range]{values}}[$iVal]\cA"; ]e; } incrRange($state, $range - 1) if $carry and $range >= 0; #print $state->{last}; } package main; my $genUrl = new GenURLs( 'test[1-10]{a,b,c}' ); my $iterator = $genUrl->getIterator(100); print $iterator->(); __END__