use re 'eval'; my $string = qr[ " [^"\\]* (?:\\.|[^"\\])* " | ' [^'\\]* (?:\\.|[^'\\])* ' ]x; my $alist = qr[(?: [^"'>]* | $string )*]x; my $ehead = qr[ <\w+ $alist /? > ]x; my $textarea = qr[ ]x; my $asp = qr[ <% (?: (?> [^%"']* ) | $string | % (?! > ) )+ %> ]x; my $html = qr[ (?: (?> [^<"'] ) | $textarea | $ehead | )+ ]x; my @parsed; () = $string =~ / ($asp) (?{ push @parsed, [asp => $1] }) | ($html) (?{ push @parsed, [html => $2] }) /gx;