Here's a brute-force approach to doing what you want, but I'm not sure it will necessarily help you solve your problem. (And permutations are applied to all whitespace, not just blanks.)
File
Odo.pm:
# Odo.pm ovedpo15 pm #11145308 06
+jul22waw
package Odo;
use strict;
use warnings;
use Data::Dump qw(dd); # for debug
sub Iterator (&) { return $_[0]; } # syntactic sugar per mjd (Dominus
+)
sub odometer {
my ($string, # string to permute
@special_chars, # single, special characters to use in "odome
+ter"
) = @_;
# offsets in string of individual whitespace characters.
my @offsets;
push @offsets, $-[0] while $string =~ m{ \s }xmsg;
# dd '-----', $string, \@offsets; # for debug
die "too few special characters to replace all whitespace found"
if @special_chars < @offsets; # minimal validation
# init odo counter for each offset plus overflow flag (inited fals
+e).
my @odo_offsets = ((0) x @offsets, 0);
# iterator to generate each string permutation.
return Iterator {
# return undef if odo overflowed (iterator permanently exhaust
+ed).
return if $odo_offsets[-1]; # overflow flag true
my $permutation = $string; # possible string permutation
# dd '+++++', \@odo_offsets; # <STDIN>; # for debug
# replace each whitespace char with permuted special character
+.
substr $permutation, $offsets[$_], 1, $special_chars[$odo_offs
+ets[$_]]
for 0 .. $#offsets;
# increment odometer for next permutation; flag odo overflow.
$odo_offsets[$_] < $#special_chars
? ($odo_offsets[$_]++, last)
: ($odo_offsets[$_] = 0)
for 0 .. $#odo_offsets;
# dd '_____', \@odo_offsets; <STDIN>; # for debug
return $permutation;
}; # end path permutation Iterator
} # end sub odometer()
1;
File
Odo.t:
# Odo.t 06
+jul22waw
use strict;
use warnings;
use Test::More;
use Test::NoWarnings;
use Data::Dump qw(dd pp);
BEGIN { use_ok 'Odo'; }
my @Tests = (
[ '/a/b/c/d/e/fi le' => # path with whitespace to permute
'/a/b/c/d/e/fi:le', # special character permutations
'/a/b/c/d/e/fi;le',
'/a/b/c/d/e/fi,le',
'/a/b/c/d/e/fi=le',
'/a/b/c/d/e/fi-le',
],
[ ' /a/b/c/d/e/file' =>
':/a/b/c/d/e/file',
';/a/b/c/d/e/file',
',/a/b/c/d/e/file',
'=/a/b/c/d/e/file',
'-/a/b/c/d/e/file',
],
[ '/a/b/c/d/e/file ' =>
'/a/b/c/d/e/file:',
'/a/b/c/d/e/file;',
'/a/b/c/d/e/file,',
'/a/b/c/d/e/file=',
'/a/b/c/d/e/file-',
],
[ '/a/b/c/d/e/fi l e' =>
'/a/b/c/d/e/fi:l:e',
'/a/b/c/d/e/fi;l:e',
'/a/b/c/d/e/fi,l:e',
'/a/b/c/d/e/fi=l:e',
'/a/b/c/d/e/fi-l:e',
'/a/b/c/d/e/fi:l;e',
'/a/b/c/d/e/fi;l;e',
'/a/b/c/d/e/fi,l;e',
'/a/b/c/d/e/fi=l;e',
'/a/b/c/d/e/fi-l;e',
'/a/b/c/d/e/fi:l,e',
'/a/b/c/d/e/fi;l,e',
'/a/b/c/d/e/fi,l,e',
'/a/b/c/d/e/fi=l,e',
'/a/b/c/d/e/fi-l,e',
'/a/b/c/d/e/fi:l=e',
'/a/b/c/d/e/fi;l=e',
'/a/b/c/d/e/fi,l=e',
'/a/b/c/d/e/fi=l=e',
'/a/b/c/d/e/fi-l=e',
'/a/b/c/d/e/fi:l-e',
'/a/b/c/d/e/fi;l-e',
'/a/b/c/d/e/fi,l-e',
'/a/b/c/d/e/fi=l-e',
'/a/b/c/d/e/fi-l-e',
],
[ "/a/b/c/d/e/fi \tle " =>
'/a/b/c/d/e/fi::le:',
'/a/b/c/d/e/fi;:le:',
'/a/b/c/d/e/fi,:le:',
'/a/b/c/d/e/fi=:le:',
'/a/b/c/d/e/fi-:le:',
'/a/b/c/d/e/fi:;le:',
'/a/b/c/d/e/fi;;le:',
'/a/b/c/d/e/fi,;le:',
'/a/b/c/d/e/fi=;le:',
'/a/b/c/d/e/fi-;le:',
'/a/b/c/d/e/fi:,le:',
'/a/b/c/d/e/fi;,le:',
'/a/b/c/d/e/fi,,le:',
'/a/b/c/d/e/fi=,le:',
'/a/b/c/d/e/fi-,le:',
'/a/b/c/d/e/fi:=le:',
'/a/b/c/d/e/fi;=le:',
'/a/b/c/d/e/fi,=le:',
'/a/b/c/d/e/fi==le:',
'/a/b/c/d/e/fi-=le:',
'/a/b/c/d/e/fi:-le:',
'/a/b/c/d/e/fi;-le:',
'/a/b/c/d/e/fi,-le:',
'/a/b/c/d/e/fi=-le:',
'/a/b/c/d/e/fi--le:',
'/a/b/c/d/e/fi::le;',
'/a/b/c/d/e/fi;:le;',
'/a/b/c/d/e/fi,:le;',
'/a/b/c/d/e/fi=:le;',
'/a/b/c/d/e/fi-:le;',
'/a/b/c/d/e/fi:;le;',
'/a/b/c/d/e/fi;;le;',
'/a/b/c/d/e/fi,;le;',
'/a/b/c/d/e/fi=;le;',
'/a/b/c/d/e/fi-;le;',
'/a/b/c/d/e/fi:,le;',
'/a/b/c/d/e/fi;,le;',
'/a/b/c/d/e/fi,,le;',
'/a/b/c/d/e/fi=,le;',
'/a/b/c/d/e/fi-,le;',
'/a/b/c/d/e/fi:=le;',
'/a/b/c/d/e/fi;=le;',
'/a/b/c/d/e/fi,=le;',
'/a/b/c/d/e/fi==le;',
'/a/b/c/d/e/fi-=le;',
'/a/b/c/d/e/fi:-le;',
'/a/b/c/d/e/fi;-le;',
'/a/b/c/d/e/fi,-le;',
'/a/b/c/d/e/fi=-le;',
'/a/b/c/d/e/fi--le;',
'/a/b/c/d/e/fi::le,',
'/a/b/c/d/e/fi;:le,',
'/a/b/c/d/e/fi,:le,',
'/a/b/c/d/e/fi=:le,',
'/a/b/c/d/e/fi-:le,',
'/a/b/c/d/e/fi:;le,',
'/a/b/c/d/e/fi;;le,',
'/a/b/c/d/e/fi,;le,',
'/a/b/c/d/e/fi=;le,',
'/a/b/c/d/e/fi-;le,',
'/a/b/c/d/e/fi:,le,',
'/a/b/c/d/e/fi;,le,',
'/a/b/c/d/e/fi,,le,',
'/a/b/c/d/e/fi=,le,',
'/a/b/c/d/e/fi-,le,',
'/a/b/c/d/e/fi:=le,',
'/a/b/c/d/e/fi;=le,',
'/a/b/c/d/e/fi,=le,',
'/a/b/c/d/e/fi==le,',
'/a/b/c/d/e/fi-=le,',
'/a/b/c/d/e/fi:-le,',
'/a/b/c/d/e/fi;-le,',
'/a/b/c/d/e/fi,-le,',
'/a/b/c/d/e/fi=-le,',
'/a/b/c/d/e/fi--le,',
'/a/b/c/d/e/fi::le=',
'/a/b/c/d/e/fi;:le=',
'/a/b/c/d/e/fi,:le=',
'/a/b/c/d/e/fi=:le=',
'/a/b/c/d/e/fi-:le=',
'/a/b/c/d/e/fi:;le=',
'/a/b/c/d/e/fi;;le=',
'/a/b/c/d/e/fi,;le=',
'/a/b/c/d/e/fi=;le=',
'/a/b/c/d/e/fi-;le=',
'/a/b/c/d/e/fi:,le=',
'/a/b/c/d/e/fi;,le=',
'/a/b/c/d/e/fi,,le=',
'/a/b/c/d/e/fi=,le=',
'/a/b/c/d/e/fi-,le=',
'/a/b/c/d/e/fi:=le=',
'/a/b/c/d/e/fi;=le=',
'/a/b/c/d/e/fi,=le=',
'/a/b/c/d/e/fi==le=',
'/a/b/c/d/e/fi-=le=',
'/a/b/c/d/e/fi:-le=',
'/a/b/c/d/e/fi;-le=',
'/a/b/c/d/e/fi,-le=',
'/a/b/c/d/e/fi=-le=',
'/a/b/c/d/e/fi--le=',
'/a/b/c/d/e/fi::le-',
'/a/b/c/d/e/fi;:le-',
'/a/b/c/d/e/fi,:le-',
'/a/b/c/d/e/fi=:le-',
'/a/b/c/d/e/fi-:le-',
'/a/b/c/d/e/fi:;le-',
'/a/b/c/d/e/fi;;le-',
'/a/b/c/d/e/fi,;le-',
'/a/b/c/d/e/fi=;le-',
'/a/b/c/d/e/fi-;le-',
'/a/b/c/d/e/fi:,le-',
'/a/b/c/d/e/fi;,le-',
'/a/b/c/d/e/fi,,le-',
'/a/b/c/d/e/fi=,le-',
'/a/b/c/d/e/fi-,le-',
'/a/b/c/d/e/fi:=le-',
'/a/b/c/d/e/fi;=le-',
'/a/b/c/d/e/fi,=le-',
'/a/b/c/d/e/fi==le-',
'/a/b/c/d/e/fi-=le-',
'/a/b/c/d/e/fi:-le-',
'/a/b/c/d/e/fi;-le-',
'/a/b/c/d/e/fi,-le-',
'/a/b/c/d/e/fi=-le-',
'/a/b/c/d/e/fi--le-',
],
[ "\t/a/b/c/d/e/fi\nle\f" =>
':/a/b/c/d/e/fi:le:',
';/a/b/c/d/e/fi:le:',
',/a/b/c/d/e/fi:le:',
'=/a/b/c/d/e/fi:le:',
'-/a/b/c/d/e/fi:le:',
':/a/b/c/d/e/fi;le:',
';/a/b/c/d/e/fi;le:',
',/a/b/c/d/e/fi;le:',
'=/a/b/c/d/e/fi;le:',
'-/a/b/c/d/e/fi;le:',
':/a/b/c/d/e/fi,le:',
';/a/b/c/d/e/fi,le:',
',/a/b/c/d/e/fi,le:',
'=/a/b/c/d/e/fi,le:',
'-/a/b/c/d/e/fi,le:',
':/a/b/c/d/e/fi=le:',
';/a/b/c/d/e/fi=le:',
',/a/b/c/d/e/fi=le:',
'=/a/b/c/d/e/fi=le:',
'-/a/b/c/d/e/fi=le:',
':/a/b/c/d/e/fi-le:',
';/a/b/c/d/e/fi-le:',
',/a/b/c/d/e/fi-le:',
'=/a/b/c/d/e/fi-le:',
'-/a/b/c/d/e/fi-le:',
':/a/b/c/d/e/fi:le;',
';/a/b/c/d/e/fi:le;',
',/a/b/c/d/e/fi:le;',
'=/a/b/c/d/e/fi:le;',
'-/a/b/c/d/e/fi:le;',
':/a/b/c/d/e/fi;le;',
';/a/b/c/d/e/fi;le;',
',/a/b/c/d/e/fi;le;',
'=/a/b/c/d/e/fi;le;',
'-/a/b/c/d/e/fi;le;',
':/a/b/c/d/e/fi,le;',
';/a/b/c/d/e/fi,le;',
',/a/b/c/d/e/fi,le;',
'=/a/b/c/d/e/fi,le;',
'-/a/b/c/d/e/fi,le;',
':/a/b/c/d/e/fi=le;',
';/a/b/c/d/e/fi=le;',
',/a/b/c/d/e/fi=le;',
'=/a/b/c/d/e/fi=le;',
'-/a/b/c/d/e/fi=le;',
':/a/b/c/d/e/fi-le;',
';/a/b/c/d/e/fi-le;',
',/a/b/c/d/e/fi-le;',
'=/a/b/c/d/e/fi-le;',
'-/a/b/c/d/e/fi-le;',
':/a/b/c/d/e/fi:le,',
';/a/b/c/d/e/fi:le,',
',/a/b/c/d/e/fi:le,',
'=/a/b/c/d/e/fi:le,',
'-/a/b/c/d/e/fi:le,',
':/a/b/c/d/e/fi;le,',
';/a/b/c/d/e/fi;le,',
',/a/b/c/d/e/fi;le,',
'=/a/b/c/d/e/fi;le,',
'-/a/b/c/d/e/fi;le,',
':/a/b/c/d/e/fi,le,',
';/a/b/c/d/e/fi,le,',
',/a/b/c/d/e/fi,le,',
'=/a/b/c/d/e/fi,le,',
'-/a/b/c/d/e/fi,le,',
':/a/b/c/d/e/fi=le,',
';/a/b/c/d/e/fi=le,',
',/a/b/c/d/e/fi=le,',
'=/a/b/c/d/e/fi=le,',
'-/a/b/c/d/e/fi=le,',
':/a/b/c/d/e/fi-le,',
';/a/b/c/d/e/fi-le,',
',/a/b/c/d/e/fi-le,',
'=/a/b/c/d/e/fi-le,',
'-/a/b/c/d/e/fi-le,',
':/a/b/c/d/e/fi:le=',
';/a/b/c/d/e/fi:le=',
',/a/b/c/d/e/fi:le=',
'=/a/b/c/d/e/fi:le=',
'-/a/b/c/d/e/fi:le=',
':/a/b/c/d/e/fi;le=',
';/a/b/c/d/e/fi;le=',
',/a/b/c/d/e/fi;le=',
'=/a/b/c/d/e/fi;le=',
'-/a/b/c/d/e/fi;le=',
':/a/b/c/d/e/fi,le=',
';/a/b/c/d/e/fi,le=',
',/a/b/c/d/e/fi,le=',
'=/a/b/c/d/e/fi,le=',
'-/a/b/c/d/e/fi,le=',
':/a/b/c/d/e/fi=le=',
';/a/b/c/d/e/fi=le=',
',/a/b/c/d/e/fi=le=',
'=/a/b/c/d/e/fi=le=',
'-/a/b/c/d/e/fi=le=',
':/a/b/c/d/e/fi-le=',
';/a/b/c/d/e/fi-le=',
',/a/b/c/d/e/fi-le=',
'=/a/b/c/d/e/fi-le=',
'-/a/b/c/d/e/fi-le=',
':/a/b/c/d/e/fi:le-',
';/a/b/c/d/e/fi:le-',
',/a/b/c/d/e/fi:le-',
'=/a/b/c/d/e/fi:le-',
'-/a/b/c/d/e/fi:le-',
':/a/b/c/d/e/fi;le-',
';/a/b/c/d/e/fi;le-',
',/a/b/c/d/e/fi;le-',
'=/a/b/c/d/e/fi;le-',
'-/a/b/c/d/e/fi;le-',
':/a/b/c/d/e/fi,le-',
';/a/b/c/d/e/fi,le-',
',/a/b/c/d/e/fi,le-',
'=/a/b/c/d/e/fi,le-',
'-/a/b/c/d/e/fi,le-',
':/a/b/c/d/e/fi=le-',
';/a/b/c/d/e/fi=le-',
',/a/b/c/d/e/fi=le-',
'=/a/b/c/d/e/fi=le-',
'-/a/b/c/d/e/fi=le-',
':/a/b/c/d/e/fi-le-',
';/a/b/c/d/e/fi-le-',
',/a/b/c/d/e/fi-le-',
'=/a/b/c/d/e/fi-le-',
'-/a/b/c/d/e/fi-le-',
],
); # end array @Tests
my @additional = qw(Test::NoWarnings use_ok); # each of these adds 1
+test
plan 'tests' => @Tests + @additional;
# special characters to permute in place of whitespace for all tests.
use constant SPECIAL_CHARS => (':', ';', ',', '=', '-');
# testing, testing... ################################################
+######
VECTOR:
for my $ar_vector (@Tests) {
if (not ref $ar_vector) {
note $ar_vector;
next VECTOR;
}
my ($path, @expected) = @$ar_vector;
my $iter = Odo::odometer($path, SPECIAL_CHARS);
my @got;
while (defined(my $possible = $iter->())) {
push @got, $possible;
}
is_deeply \@got, \@expected, pp $path;
} # end for VECTOR