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