sub mysplit { my $string = shift; my @parts; my $part = ''; my $escaped = 0; for ($string =~ m/(.)/gs) { if ($_ eq '@') { unless ($escaped) { push @parts, $part; $part = ''; next; } } if ($_ eq "#") { $escaped ^= 1; # toggle state } else { $escaped = 0; # reset } $part .= $_; } push @parts, $part; return @parts; } my @tests = ( 'one@two@three', '## is a hash and #@ is an arobace', '#@##@###@####@#####@', ); for my $s (@tests) { print join(', ', mysplit($s) ), "\n"; }