PHP preg_match с регулярным выражением: только отдельные дефисы и пробелы между словами

Как разрешить одиночные дефисы и отдельные пробелы только в словах, но не в начале или в конце слов?

if(!preg_match('/^[a-zA-Z0-9\-\s]+$/', $pg_tag)) { $error = true; echo '<error elementid="pg_tag" message="TAGS - only alphanumbers and hyphens are allowed."/>'; } 

Я не хочу принимать эти данные ниже

 ---stack---over---flow--- stack-over-flow- stack-over-flow2 stack over flow 

но только они приемлемы,

 stack-over-flow stack-over-flow2 stack-over-flow3 stack over flow stacoverflow 

Благодарю.

     $aWords = array( 'a', '---stack---over---flow---', ' stack over flow', 'stack-over-flow', 'stack over flow', 'stacoverflow' ); foreach($aWords as $sWord) { if (preg_match('/^(\w+([\s-]\w+)?)+$/', $sWord)) { echo 'pass: ' . $sWord . "\n"; } else { echo 'fail: ' . $sWord . "\n"; } } 

    И выход:

     pass: a fail: ---stack---over---flow--- fail: stack over flow pass: stack-over-flow pass: stack over flow pass: stacoverflow 

    Распределение регулярного выражения:

     ^ # Match from the very beginning of the string ( # Start Group \w+ # At least one "word" character ( # Start Subgroup [\s-] # A single space or a dash \w+ # At least one "word" character )? # End Subgroup is optional )+ # End group - allow it multiple times $ # Match until the very end of the string 

    Что касается комментариев: другая идея – «нормализовать» ввод, т. Е. Сократить все последовательные пробелы и тире до одного и удалить их с начала и конца:

     $pg_tag = preg_replace(array('/\s+/', '/-+/'), array(' ', '-'), trim($pg_tag, ' -')); 

    Ссылка: preg_replace , trim

    Чтобы принять символ или цифру с пробелом между ними. В случае только пробела он не проходит тест или не принимает его.

    Это регулярное выражение принимает строку типа «Главная работа», но с ошибкой «».

     var pattern = /^(?=.*\S)[.+a-z0-9A-Z-.#:!*$^_|?` ]+$/; return pattern.test(value); 

    Это возвращает true, если строка принята.