You subtly changed the OPs
(.*) into a
([^.]+)? Did you do that on purpose? I believe so, otherwise, the line:
return $str =~ m/\@([^.]+)/ ? $1 : '';
doesn't make sense. The OP original patters allows for the capture of an empty string; and an undefined value will be returned if there was no match. If your pattern is changed to allow empty string matches, you can no longer distinguish between "not a match", and "empty match". You also leave off the matching of a dot, meaning you match on
foo@bar, where the OP doesn't. Finally, there's no need to escape the @.
sub name {
return $1 if $_[0] =~ /@([^.*])\./;
}