Быть конкретным - лучший вариант.Но вы также можете использовать утверждение:
preg_match("/^(?![- ])([a-z -])+$/i", $str)
(?!..)
может исключить появление символов в первую очередь.Вы также можете использовать положительное утверждение, например (?=\w)
.