The form validation code you've shown takes a URL-encoded escape sequence (like %7E) and replaces it with the character it encoded (like "~"). But you should let CGI.pm take care of your form processing. It does it right.
As for the number of times a pattern appears in a string, I'd suggest: my $count = 0; ++$count while $string =~ /$pattern/g;