Регулярное выражение, разрешающее только 1 из набора символов - PullRequest
2 голосов
/ 10 июля 2020

Я пытаюсь использовать какое-то регулярное выражение для проверки ввода внутри кода Java. Мне удалось реализовать регулярное выражение «basi c», но это, похоже, выходит за рамки моих знаний. Я работаю с обучающими программами RegEgg, чтобы узнать больше.

Вот условия, которые необходимо проверить:

  • Поле всегда будет иметь 8 символов
  • Может быть все пробелы

или

  • Допустимые символы: a-zA-Z0-9 -! & или пробел
  • Не может начинаться с пробела
  • Если используется один из специальных символов, он может быть единственным используемым. Допустимый: "B-123 ---" "AB && &" "A !!!!!!!" Нелегально: «Б-123 !!!» «AB && -» «A- &!»
  • Должен содержать как минимум один буквенно-цифровой символ c (не могут быть все специальные символы ie: «!!!!!!!!»

Это было мое регулярное выражение до того, как были добавлены дополнительные проверки:

^(\s{8}|[A-Za-z\-\!\&][ A-Za-z0-9\-\!\&]{7})$"

Затем дополнительные проверки на данный момент позволяют использовать несколько специальных символов, и я немного застрял. Я был успешно использовал положительный просмотр назад, но застрял при попытке использовать положительный просмотр назад (я думаю, что данные до просмотра назад были использованы), но я размышляю, поскольку я новичок в этой части регулярного выражения.

Ответы [ 2 ]

2 голосов
/ 10 июля 2020

использование конструкции or (a|b) составляет большую часть этого, и вы начали применять его, так что это хорошее начало.

Вы сделали правило, что это не может начинать с цифры; ничего в спе c об этом не сказано. Кроме того, - внутри [] имеет особое значение, поэтому избегайте его или убедитесь, что он первый или последний, потому что тогда вам не нужно. Это приводит нас к следующему:

^(\s{8}|[A-Za-z0-9-!& -]{8})$

следующее правило: это должен быть один и тот же специальный символ, если он вообще используется. Учитывая, что есть только 3 специальных символа, может быть проще просто явно перечислить их все:

^(\s{8}|[A-Za-z0-9 -]{8}|[A-Za-z0-9 !]{8}|[A-Za-z0-9 &]{8})$

Далее: не может начинаться с пробела и не может быть все-особенное. Подтверждение отрицательного (что это все специальные символы ISNT) усложняется; взгляд вперед кажется здесь лучшим планом. Это:

^ является регулярным выражением для: «Начало строки». Обратите внимание, что это не «потребляет» персонажа. 1 является регулярным выражением для «здесь будет соответствовать только точный символ« 1 », ничего больше», но при совпадении он также «потребляет» этот символ, тогда как ^ этого не делает. «начало строки» не является концепцией, которую можно использовать.

Это понятие «совпадение может быть неудачным, но в случае успеха ничего не используется» не ограничивается ^ и $ ; вы можете написать свой собственный:

(?=abc) будет соответствовать, если abc будет соответствовать в этой позиции, , но не потребляет его . Таким образом, регулярное выражение ^(=abc)ab.d$ будет соответствовать входной строке abcd и ничему другому. Это называется положительный просмотр вперед . (он «смотрит вперед» и соответствует, если видит регулярное выражение в скобках, и терпит неудачу, если нет).

(?!abc) равно отрицательный просмотр вперед . Он совпадает, если он НЕ видит вещь в скобках. (?!abc)a.c будет соответствовать входу adc, но не входу abc.

(?<=abc) это положительный просмотр назад . Он совпадает, если предоставленный вами шаблон будет соответствовать так, что совпадение заканчивается в позиции, в которой вы оказались.

(?<!abc) это отрицательный просмотр назад .

Обратите внимание, что просмотр вперед и назад может быть несколько ограничен, поскольку они могут не допускать шаблонов переменной длины. Но, к счастью, ваши требования позволяют легко ограничиться выкройками фиксированного размера. Таким образом, мы можем ввести: (?![&!-]{8}) как непотребляющую единицу в нашем регулярном выражении, которая не будет соответствовать, если у нас есть все 8 специальных символов.

Мы можем использовать этот трюк и для сбоя в начальном пространстве: (?! ) - это все, что нам нужно для этого.

Давайте заменим \s, который является пробелом , просто , который является пробелом (в описании проблемы написано «пробел», а не пробел).

Собираем все вместе:

^( {8}|(?! )(?![&!-]{8})([A-Za-z0-9 -]{8}|[A-Za-z0-9 !]{8}|[A-Za-z0-9 &]{8}))$

Вот:

  1. 8 пробелов, или ...
  2. не пробел и не специальный символ из всех 8, тогда
  3. любой из допустимых символов, любое количество пробелов и любое количество одного из 3 разрешенных специальных символов, как пока у нас их ровно 8 ...
  4. .. ИЛИ то же самое, что и # 3, но со вторым из трех специальных символов
  5. .. ИЛИ с третьим из трех .

Подключите их к regex101 вместе с вашими различными примерами «легальных» и «незаконных», и вы можете играть в aro и еще кое-что.

NB: Вы также можете использовать обратные ссылки, чтобы попытаться решить часть этой задачи «разрешен только один специальный символ», но попытка решить часть «не все специальные символы» кажется довольно сложной. громоздко, если вы не можете использовать (отрицательный) просмотр вперед.

0 голосов
/ 10 июля 2020

Это вопрос утверждения правильных условий в начале регулярного выражения.

^(?=[ ]*$|(?![ ]))(?!.*([!&-]).*(?!\1)[!&-])[a-zA-Z0-9 !&-]{8}$

см. -> https://regex101.com/r/tN5y4P/1

Некоторое обсуждение:

 ^                      # Begin of text
 (?=                    # Assert, cannot start with a space
      [ ]* $            # unless it's all spaces
   |  (?! [ ] )
 )
 (?!                    # Assert, not mixed special chars
      .* 
      ( [!&-] )         # (1)
      .* 
      (?! \1 )
      [!&-] 
 )
 [a-zA-Z0-9 !&-]{8}     # Consume 8 valid characters from within this class
 $                      # End of text
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...