Perl already provides the functionality you describe. So, unless you have a specific reason for re-inventing the wheel (which may be perfectly valid but isn't addressed in your post), you can use code like this to achieve what you're after.

Here's some of the things you could have done better in the code you provided:

Let Perl tell you when you're doing something potentially problematic, or just plain wrong, with strict and warnings. See usage in my code.

Declare your variables. my is used most often - see my %ex and my $k in my code. With no declarations, all your variables become global which has all sorts of implications and is basically a headache you don't need to have. (There are other ways to declare variables - see perlsub for details.)

You call your subroutine with an argument (perlhash($k)) but don't read that argument in the subroutine code. In this instance, my $k = shift; would have been sufficient; for multiple arguments, use something like my ($arg1, ..., $argN) = @_; - see perlsub for details.

It's easy to mistype, misread or miscount the exact number of arrayrefs in @buckets = ( [],[],[],[],[],[],[],[],[],[] );. You can use the x operator to avoid all three types of problems: @buckets = ([]) x 10; - see perlop for details.

When you read user input (typed from the keyboard) you'll get all the keystrokes including the final return. Use chomp to remove this (as I did in my code).

Your code would be easier to read if it was laid out a little better - perlstyle has some suggestions regarding this.