Do you have to use regexp? In the past, I've solved this issue by splitting string on "escapes", and then walking all parts merging 2 subsequent "escapes" into character and placing them back into text.
Something like this
my @parts = split /([\\@])/, $input;
my $txt = shift @parts;
while(@parts > 1)
{
shift @parts;
my $t = shift @parts;
if($t eq '')
{
# get the escaped "escape"
$txt .= shift @parts;
# get the text that follows it
$txt .= shift @parts;
next;
}
$t =~ s/^(\w+)//;
my $cmd = $1;
$txt .= "::$cmd\::$t";
}
$txt .= shift @parts if @parts;