{ package Cut; sub from_list { my( $spec ) = @_; map [ $_->[1] < $_->[0] ? reverse @_[ $_->[1] .. $_->[0] ] : @_[ $_->[0] .. $_->[1] ] ], map [ /(.*)\s*-\s*(.*)/ ? ( $1, $2 ) : ( $_, $_ ) ], split /\s*,\s*/, $spec; } sub from_string { my( $spec, $input ) = @_; my @spec = map [ /(.*)\s*-\s*(.*)/ ? ( $1, $2 ) : ( $_, $_ ) ], split /\s*,\s*/, $spec; my $ofs=0; my %reverse; my @pat; for ( 0 .. $#spec ) { my( $lo, $hi ) = @{ $spec[$_] }; if ( $hi < $lo ) { $reverse{$_} = 1; ( $lo, $hi ) = ( $hi, $lo ); } my $move = $lo - $ofs - 1; my $len = $hi - $lo + 1; $ofs = $hi; $pat[$_] = ( $move > 0 ? 'x'.$move : $move < 0 ? 'X'.(-$move) : '' ) . 'a'.$len; } my @result = unpack "@pat", $input; $result[$_] = reverse $result[$_] for keys %reverse; @result } } # some test cases: my @a = Cut::from_string( '1,3-4,6-10,12-8,1,1,1', join '', 'a'..'z' ); print "'$_'\n" for @a; my @b = Cut::from_list( '1,3-4,6-10,12-8,1,1,1', 'a'..'z' ); print "> @$_\n" for @b;