OK, to match those possible characters (and only those) try something like
m/((?:\w|\\\&|\-)*)\.((?:\w|\\\&|\-)*)/
the \w takes care of letters, numbers and _. I always escape the - out of habit but is unnecessary. The /i is redundant since the \w is case insensitive.
Personally I would do a nongreedy match. It will match other characters but it probably won't matter. Something like:
m/(.*?)\.(.*)/
update --
of course a simple split would do the trick.
my ($client, $project, $subproject) = split /\./, $x;
--
flounder