Warning: I don't know if this is a correct solution. But it seems like it works, so I offer it up for criticism, just because it seems nifty:
use strict;
use warnings;
use Regexp::Common;
my $str = "a<<a> a>b<a>c<a>a";
while ($str=~/\G(?:|$RE{balanced}{-parens=>'<>'})
([^<]+)
(?:|$RE{balanced}{-parens=>'<>'})/xg)
{
# Update: Oops, this uppercases everything except what
# the OP wanted :)
substr($str, $-[1],$+[1]-$-[1]) = uc $1;
pos($str) = $+[1];
}
Update: I should read the OP again. This seems to match, but doesn't change the case like the OP wants. Nevermind (for now) :(
Update: Fixed. Though I'm still not sure if it's absolutely correct :)
Update (simplified solution below): $str =~ s/(^|\G$RE{balanced}{-parens=>'<>'})([^<]+)/\U$1\E$2/g;
# Again? (and now I feel a DUH! coming on (:
$str =~ s/($RE{balanced}{-parens=>'<>'})/\U$1/g;
|