Parsing Perl is difficult, and the rules for what is and is not a variable are complicated. If you're attempting to parse Perl, consider using PPI instead. It can parse a Perl program and do things like find all the variables. PPI is what perlcritic uses to do its job.
If you want to try and do it anyway, here's some edge cases to consider...
$^F
$/
${^ENCODING}
$1
$élite # with utf8 on
${foo}
*{foo} = \42;
*{$name} = \42; # with strict off
${$name} = 42; # with strict off
And of course the other sigils @%*. And detecting if something is inside a single quoted string. Which is my way of strongly encouraging you to use PPI rather than try to do it yourself.
If you want practice, realistic practice is to pull the variable out of a larger string, rather than do exact matches.
# Match the various sigils.
my $sigils = qr{ [\$\@\%*] }x;
# Match $1 and @1 and so on
my $digit_var = qr{ $sigils \d+ }x;
# Match normal variables
my $named_var = qr{ $sigils [\w^0-9] \w* }x;
# Combine all the various variable matches
my $match_variable = qr{ ( $named_var | $digit_var ) }x;
This uses the () capture operator to grab just the variable. It also uses the /x modifier to make the regex easier to read and alternative delimiters to avoid leaning toothpick syndrome. Using \w instead of A-Z ensures that Unicode characters will be picked up when utf8 is on, and that they won't when its off. Finally, qr is used to build up the regex in pieces. Filling in the gaps is left as an exercise.