my $nbridx = 1; my $filename; while( $filename = ) { next if $filename =~ m/^\s*#/; chomp( $filename ); # First split filename into alternating non-numeric and numeric # chunks. Any defined string will match here. my @a = $filename =~ m/ (\D+)? (\d+)? /xg; # The m//g always tries once too many, so throw away the last # two array elements. splice(@a,-2,2); # An empty string would result in an empty array. next unless @a; # Leading/embedded/trailing spaces are not dealt with here. # Now we have an array where numeric chunks are at odd-numbered # indexes and non-numeric chunks are at even-numbered indexes. # Note that the leading and/or trailing elements may be undef. # Examples: # 'number.', '9' # '', '1', '.cgi', '' # 'bottles', '99', '.ale', '' # printf "I split into '%s'\n", join("', '", doud(@a) ); # Figure out how many number chunks exist in this array then # check against how many are needed. my $nbrcnt = int( scalar(@a) / 2 ); $nbrcnt-- unless defined $a[-1]; if( $nbridx == 0 or abs($nbridx) > $nbrcnt ) { printf "This filename only has %d number chunks and you asked for the %d'th one!\n", $nbrcnt, $nbridx; next; } # Now a little math to figure out the array index of wanted number my $chkidx = ($nbridx>0) ? ( $nbridx * 2 - 1 ) : ( ($nbridx + $nbrcnt) * 2 + 1 ); # printf " Desired index %d Number Chunks %d Internal index %d\n", # $nbridx, $nbrcnt, $chkidx; # All the actual manipulation of $a[$chkidx] would be the # next little bit (cough) to implement here # Show the chunk we operated on and rebuild the string. $filename = join( '', grep { defined $_ } @a ); printf " Using '%s' from '%s'\n", $a[$chkidx], $filename; } sub doud { map { defined($_) ? $_ : '' } @_ }; __END__ wrong_number! 01-file02.html 11-file22tom33bill.html 1.cgi number.9 bottles99.ale 0bottles.beer 666 #### my @a = $filename =~ m/ (\D+)? (\d+)? /xg;