use strict; use warnings; use re 'eval'; my $begin = qr!\Q[xyz]!; my $end = qr!\Q[/xyz]!; my @match; my $re; $re = qr{ $begin ( (?: (?> (?:(?!=$begin|$end).)+ ) | (??{ $re }) )* ) $end }x; $_ = '[xyz][xyz]level 1.1 [xyz]level 2.1[/xyz] rest of 1.1 [/xyz]'; 1 while s!$re!$1!; print; __END__ level 1.1 [xyz]level 2.1 rest of 1.1