PHP preg_match с регулярным выражением: продолжаются только одиночные дефисы и пробелы между словами - PullRequest
1 голос
/ 09 февраля 2011

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

Я думал, что это отсортировано из ответа Я получил вчера, но я только что понял, что есть небольшая ошибка, которую я не совсем понимаю,

Почему он не принимает такие входные данные, как,

'forum-category-b forum-category-a'
'forum-category-b Counter-terrorism'
'forum-category-a Preventing'
'forum-category-a Preventing Violent'
'forum-category-a International-Research-and-Publications'
'International-Research-and-Publications forum-category-b forum-category-a'

но требуется,

'forum-category-b'
'Counter-terrorism forum-category-a'
'Preventing forum-category-a'
'Preventing Violent forum-category-a'
'International-Research-and-Publications forum-category-b'

Почему это? Как я могу это исправить? Ниже приведено регулярное выражение с начальным тестом, но в идеале он должен принимать все входные данные комбинации, указанные выше,

$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";
    }
}

принять / отклонить ввод, как показано ниже,

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

Спасибо.

Ответы [ 3 ]

1 голос
/ 09 февраля 2011

Ваш шаблон не делает то, что вы хотите.Давайте разберем его на части:

^(\w+([\s-]\w+)?)+$

Соответствует строкам, которые состоят только из одной или нескольких последовательностей шаблона:

\w+([\s-]\w+)?

..., который представляет собой последовательность символов слова с последующимпо выбору - еще одна последовательность символов слова, разделенных одним пробелом или тире.

Другими словами, ваш шаблон ищет строки вроде:

xxx-xxxyyy-yyyzzz zzz

... но вы намереваетесьнапишите шаблон, который найдет:

xxx-xxxxxx-xxxxxx yyy

В ваших примерах это соответствует:

Counter-terrorism forum-category-a

... но это интерпретируется как следующая последовательность:

(Counter(-terroris)) (m( foru)) (m(-categor) (y(-a))

Как вы можете видеть, шаблон действительно не нашел слова, которые вы ищете.

Этот пример не соответствует:

forum-category-a Preventing Violent

...поскольку шаблон не может образовывать группы из «символов слова, пробела или тире, символов слова», когда он встречает один символ слова, за которым следует пробел или тире:

(forum(-categor)) (y(-a)) <Mismatch: Found " " but expected "\w">

Если вы добавите еще один символ в"форум-категория-а", скажем "форум-категория-топор", это будет соответствоватьснова, так как он может разделиться на «топор»:

(forum(-categor)) (y(-a)) (x( Preventin)) (g( Violent))

Что вас действительно интересует, так это шаблон типа

^(\w+(-\w+)*)(\s\w+(-\w+)*)*$

... который найдетпоследовательность слов, которые могут содержать тире, разделенные пробелами:

(forum(-category)(-a)) ( Preventing) ( Violent)

Кстати, я проверил это с помощью скрипта Python и пытаясь сопоставить ваш шаблон с примером строки "International«Форум исследований-публикаций-форум-категория-b форум-категория-а», механизм регулярных выражений, похоже, запутался в бесконечном цикле ...

import re
expr = re.compile(r'^(\w+([\s-]\w+)?)+$')
expr.match('International-Research-and-Publications forum-category-b forum-category-a')
0 голосов
/ 09 февраля 2011

На эту проблему должен быть только один ответ:

/^((?<=\w)[ -]\w|[^ -])+$/

Существует только одно правило, как указано \w[ -]\w и это все. И это на на символьную детализацию, и не может быть иным. Добавьте [^ -] для остальных.

0 голосов
/ 09 февраля 2011

часть вашего паттерна ([\s-]\w+)? - это проблема.Это допускает только одно повторение (трейлинг ?).Попробуйте изменить последний ? на * и посмотрите, поможет ли это.

Нет, я все еще считаю, что это проблема.Исходный шаблон ищет слово или слово [space_hyphen] word, повторенное 1+ раз.Что странно, потому что шаблон должен попадать в другое совпадение.Но переключение знака вопроса у меня сработало .

...