This isn't something that can be done in one regular expression, no matter
how complicated. To find something between two single characters, a pattern
like /x([^x]*)x/ will get the intervening bits in $1. For multiple ones, then something more
like
/alpha(.*?)omega/ would be needed. But none of these deals with nested patterns, nor can
they. For that you'll have to write a parser.

If you are serious about writing a parser, there are a number of modules or oddities that will make your life a lot easier. There is the
CPAN module Parse::RecDescent, the standard module Text::Balanced, the byacc program, and Mark-Jason Dominus's excellent
py tool at http://www.plover.com/~mjd/perl/py/
.

One simple destructive, inside-out approach that you might try is to pull
out the smallest nesting parts one at a time:

while (s//BEGIN((?:(?!BEGIN)(?!END).)*)END/gs) {
# do something with $1
}