Шаблон Regex, позволяющий использовать буквенно-цифровые и квадратные скобки с текстом внутри
Я использую regex для разрешения буквенно-цифровых символов, подчеркивания, дефиса и квадратных скобок в текстовом поле. regex, который я использую для проверки ввода, имеет вид
r'^[a-zA-Z0-9_\-\[\] ]*$.
Мне нужно изменить регекс таким образом, чтобы при наличии пустых скобок он возвращал false.
Выборочные случаи
"Ваше сообщение здесь" - Действительное
"Ваше [текстовое] сообщение здесь" - Действительное
"ваш_текст_сообщения [текст]" - valid
"Ваше [] сообщение здесь" - Недействительно
"[] сообщение" - Недействительно
Может ли это быть так?
^(?!.*\[\s*\].*)[a-zA-Z0-9_\-\[\] ]*$
В приведенных примерах должна работать следующая схема, хотя может существовать и более лаконичная версия:
^[a-zA-Z0-9_\- ]*(?:\[[a-zA-Z0-9_\- ]+\])?[a-zA-Z0-9_\- ]*$
Вкратце:
- Мы не включаем квадратные скобки в наше начальное соответствие
- Мы используем необязательную группу не захвата, чтобы убедиться, что все, что находится между квадратными скобками, соответствует правильному шаблону .
- Затем мы повторяем это начальное соответствие в конце.
Попробуйте использовать это выражение:
import re
lst = ["Your message here", "Your [text] message here", '[] jrejnei', 'ggyy [] uhihihu']
pattern = re.compile(r'^(?!.*\[\s*\])[a-zA-Z0-9_\-\[\] ]*$')
for i in lst:
if pattern.search(i):
print(i)
Вывод:
Your message here
Your [text] message here
Объяснение: Regex 101
Это можно решить с помощью группировки и повторений с использованием шаблона ^(([\w\- ])+(\[[\w\- ]+\])*)+$
. Я упростил задачу, используя \w
, который будет соответствовать любому символу <слову, то есть алфавитно-цифровым символам плюс подчеркиванию. Шаблон соответствует любому из \w
, -
или
, повторенному хотя бы один раз, за которым следует любое количество необязательных секций, заключенных в скобки (содержащих тот же шаблон). Весь шаблон должен быть повторен хотя бы один раз (таким образом, пустая строка исключается).
Прелесть в том, что для этого не нужно заглядывать вперед или назад, достаточно просто повторить соответствующие группы.
Код ниже
import re
pat = re.compile(r'^(([\w\- ])+(\[[\w\- ]+\])*)+$')
for x in ["Your message here", "Your [text] message here", "your_text_message [text]", "Your [] message here", "[] message"]:
if re.search(pat, x):
print(f"{x} - Valid")
else:
print(f"{x} - Invalid")
печатает
Your message here - Valid
Your [text] message here - Valid
your_text_message [text] - Valid
Your [] message here - Invalid
[] message - Invalid
Добавление некоторых поведений, которые могут показаться вам интересными:
Примите более одного блока скобок :
✔️[user] lives in [city]
Как вы упомянули в комментарии, ограничьте длину слова внутри блока скобок :
✔️[text]
принято
❌ но не[something_too_long_for_you]
Убедитесь, что слово в блоке скобок является переменной :
✔️[super_man_1]
принято
❌ но не[21_pilots]
ни[week-end]
, ни[?shit!]
Допускаются необязательные пробелы в блоке скобок :
✔️[ text ]
Прием подчеркиваний с поддержкой Юникода :
✔️Cañon City: [text]
Примите пунктуацию :
✔️[user], it's fine, no?
Не принимать блоки с незакрытыми скобками :
❌Hey [ this is not valid
Для регулярного выражения я использовал следующие флаги :
Ex расширенная нотация regex (называемая verbose в Python), чтобы добавить добавить несколько комментариев, чтобы сделать его читабельным.
Флаг чувствительности к регистру i для записи
[a-z]
вместо[a-zA-Z]
.u флаг никода, чтобы
\w
также соответствовал подчеркнутым буквам.
Шаблон regex, на Python :
import re
regex_pattern = r"""
^
# A block, 0 or several times, with 2 alternatives:
(?:
# A valid char: letter, space or a simple punctuation char.
[\w \-.,:;!?'\"]
|
# Brackets with a var of max 15 chars, with optional spaces around:
\[\s* # Opening bracket and optional spaces.
[a-z][a-z_0-9]{,14} # A valid variable name.
\s*\] # Optional spaces and closing bracket.
)*
$
"""
regex = re.compile(regex_pattern, re.VERBOSE | re.UNICODE | re.IGNORECASE)
tests = [
"Your [text] message here",
"[username] wrote [text]",
"your_text_message [text]",
"With optional spaces in around the word [ text ] [ user_id]",
"A message without brackets, but with \"valid\" punctuation.",
"Accents allowed with unicode support, it's Okây?",
"Your [] message here",
"[] message",
"Missing text between brackets [ ]",
"To much stuff between brackets [A23456789B123456]",
"Again word more than 15 chars [ this_one_is_long ]",
"Invalid var name: [not-valid-var]",
"Invalid var name: [2do]",
"Invalid var name: [user.name], could be accepted if you change the rule."
]
for test in tests:
print(test)
if regex.match(test):
print("OK\n")
else:
print("NOT OK\n")
Протестируйте и поиграйте с regex здесь: https://regex101.com/r/zE73Wu/1
Или запустите полный Python код здесь: https://onecompiler.com/python/42fx3xgd6