use strict; use warnings; my $str = 'A[ACGT]G[TG]G[ACT]C[AT]'; # or whatever my $strings = [ $str ]; while ( index ( $$strings[0], '[' ) > -1 ) { $strings = expand ( $strings ) ; } print "$_\n" for @$strings; sub expand { my $arg = shift; my @to_expand = @$arg; my $idx1 = index $to_expand[0], '['; my $idx2 = index $to_expand[0], ']'; my $post = substr $to_expand[0], $idx2 + 1; my @expanded; foreach my $item ( @to_expand ) { my $pre = substr $item, 0, $idx1; for ( $idx1 + 1 .. $idx2 - 1 ) { push @expanded, $pre . substr ( $item, $_, 1 ) . $post; } } return \@expanded; }