Regex для соответствия, если строка * только * содержит * все * символы из набора символов, плюс необязательный
Я столкнулся с проблемой wee с Java regex. (Должен сказать заранее, я не очень опытен ни в Java, ни в регулярном выражении.)
У меня есть строка и набор из трех символов. Я хочу узнать, построена ли строка из только этих символов. Кроме того (только для того, чтобы сделать его еще более сложным), в строке должны быть два символа должны, а третий - ** необязательный *.
У меня есть решение, мой вопрос скорее, если кто-нибудь может предложить что-то лучшее/более приятное/более элегантное, потому что это заставляет меня плакать кровью, когда я смотрю на нее...
Настройка
-
Обязательные символы: |
(pipe) и -
(тире).
Строка, о которой идет речь, должна строиться из их комбинации. Они могут быть в любом порядке, но должны быть в нем.
-
Необязательный символ: :
(двоеточие).
Строка может содержать двоеточие, но не должна. Это единственный допустимый символ, кроме двух выше.
-
Любые другие символы запрещены.
Ожидаемые результаты
Следующие строки должны работать/не работать:
"------" = false
"||||" = false
"---|---" = true
"|||-|||" = true
"--|-|--|---|||-" = true
... и...
"----:|--|:::|---::|" = true
":::------:::---:---" = false
"|||:|:::::|" = false
"--:::---|:|---G---n" = false
... и т.д..
"Уродливое" решение
Теперь у меня есть решение, которое, похоже, работает на основе qaru.site/info/556894/.... Причина, по которой мне хотелось бы лучше, станет очевидной, когда вы оправились от этого:
if (string.matches("^[(?\\:)?\\|\\-]*(([\\|\\-][(?:\\:)?])|([(?:\\:)?][\\|\\-]))[(?\\:)?\\|\\-]*$") || string.matches("^[(?\\|)?\\-]*(([\\-][(?:\\|)?])|([(?:\\|)?][\\-]))[(?\\|)?\\-]*$")) {
//do funny stuff with a meaningless string
} else {
//don't do funny stuff with a meaningless string
}
Разрушение
Первое регулярное выражение
"^[(?\\:)?\\|\\-]*(([\\|\\-][(?:\\:)?])|([(?:\\:)?][\\|\\-]))[(?\\:)?\\|\\-]*$"
проверяет все три символа
Следующий
"^[(?\\|)?\\-]*(([\\-][(?:\\|)?])|([(?:\\|)?][\\-]))[(?\\|)?\\-]*$"
проверьте только два обязательных.
... Да, я знаю...
Но поверь мне, я попробовал. Ничто другое не дало желаемого результата, но разрешено через строки без обязательных символов и т.д.
Вопрос в том, что...
Кто-нибудь знает, как сделать это более простым/более элегантным способом?
Бонусный вопрос: есть одна вещь, которую я не совсем понимаю в регулярных выражениях выше (более одного, но это меня больше всего беспокоит):
Насколько я понимаю (?) регулярные выражения, (?\\|)?
должен означать, что символ |
либо содержится, либо нет (если я не ошибаюсь), все еще в приведенной выше настройке, похоже, персонаж. Это, конечно, соответствует моей цели, но я не могу понять, почему это работает именно так.
Итак, если кто-нибудь может объяснить, чего я там пропустил, это было бы здорово, кроме того, я подозреваю, что держит ключ к более простому решению (проверка как обязательных, так и необязательных символов в одном регулярном выражении была бы идеальной.
Спасибо всем за чтение (и страдание) через мой вопрос и еще большее спасибо тем, кто отвечает.:)
PS
Я попробовал такие вещи, как ^[\\|\\-(?:\\:)?)]$
, но это не обеспечило бы обязательные символы all.
Ответы
Ответ 1
Используйте регулярное выражение, основанное на просмотре.
^(?=.*\\|)(?=.*-)[-:|]+$
или
^(?=.*\\|)[-:|]*-[-:|]*$
или
^[-:|]*(?:-:*\\||\\|:*-)[-:|]*$
DEMO 1
DEMO 2
-
(?=.*\\|)
ожидает как минимум один канал.
-
(?=.*-)
ожидает как минимум один дефис.
-
[-:|]+
любой char из списка один или несколько раз.
-
$
Конец строки.
Ответ 2
Вот простой ответ:
(?=.*\|.*-|.*-.*\|)^([-|:]+)$
Это говорит о том, что строка должна иметь '-', за которой следует '|', или '|' за которым следует "-", с нетерпением. Затем строка соответствует только допустимым символам.
Демо: http://fiddle.re/1hnu96
Ответ 3
Вот один без lookbefore и -hind.
^[-:|]*\\|[-:|]*-[-:|]*|[-:|]*-[-:|]*\\|[-:|]*$
Это не масштабируется, поэтому решение Avinash должно быть предпочтительным - если ваша система регулярных выражений имеет lookbe *.