RegExp. Разрешить только один разделитель в тексте при двух возможных вариантах

Была задача запретить использовать два разделителя подряд при заполнении текстового поля в форме. При этом разделителем может служить как пробел, так и дефис.

Написал так:

^(?!.*\-$)(?!.*([\-\s])\1)(.)+$

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

Как в данном выражении запретить использовать пробел и дефис вместе?

https://regex101.com/r/XKnAj0/2


Ответы (2 шт):

Автор решения: vsemozhebuty

Почему бы тогда не просто так:

^(?!.*\-$)(?!.*[\-\s]{2})(.)+$
→ Ссылка
Автор решения: Wiktor Stribiżew

Дело в том, что ([\-\s])\1 находит двойной дефис или пробельный символ, так как первый символ захватывается в подмаску №1, а обратная ссылка \1 находит именно такой же символ.

Вам нужно просто повторить поиск дефиса либо пробельного символа, [-\s][-\s], или [-\s]{2} или ([-\s])(?1) ((?1) повторяет шаблон первой захватывающей подмаски, здесь использовать не советую, просто для иллюстрации возможностей библиотеки PCRE).

Используйте

^(?!.*[-\s][-\s]).*[^-]$
^(?!.*[-\s]{2}).+$(?<!-)

См. пример работы выражения. Экранировать дефис в начальной позиции в символьных классах не требуется.

Подробности

  • ^ - начало строки
  • (?!.*[-\s]{2}) - блок предварительного просмотра вперёд, который отменяет совпадение, если сразу справа от текущей позиции есть 0 и более символов, отличных от перевода строки, как можно больше, а потом два пробельных символа или дефиса
  • .* - 0 и более символов, отличных от перевода строки, как можно больше
  • .+ - 1 и более символов, отличных от перевода строки, как можно больше
  • [^-] - любой символ кроме -
  • $ - конец строки
  • (?<!-) - блок предварительного просмотра назад, который отменяет совпадение, если сразу слева от текущей позиции есть -.
→ Ссылка