Я новичок в регулярном выражении и не знаю, как именно задать этот вопрос, но сделаю все возможное.
Вот простое выражение, с которым я работаю:
"^[0-9]{13}$"
Это соответствует строке чисел длиной ровно 13 символов. Согласно документации Python, я могу установить такой диапазон, который будет соответствовать строке чисел длиной от 13 до 20 символов, например:
"^[0-9]{13,20}$"
Мой вопрос: как я могу исключить определенные «длины» из диапазона? Например:
"^[0-9]{13,20 EXCEPT for 15 or 17}$"
В этом примере я хочу включить любую длину от 13 до 20, ЗА ИСКЛЮЧЕНИЕМ 15 и 17.
Это возможно?
Я просмотрел документацию по регулярным выражениям Python 3 и лично не могу найти способ сделать это, но у меня еще нет опыта работы с этим, поэтому я мог что-то упустить.
2 ответа
Ну... да, можно, но для этого потребуется больше, чем один квантификатор.
^
(?:
[0-9]{13,14} # 13 or 14
|
[0-9]{16} # or 16
|
[0-9]{18,20} # or 18, 19, 20.
)
$
^
(?!.{15}$)(?!.{17}$) # Assure that the length is neither 15 nor 17,
[0-9]{13,20} # and at the same time, 13 <= length <= 20.
$
^
[0-9]{13,20} # Basically the same pattern,
(?<!^.{15})(?<!^.{17}) # just inverted.
$
С обычным кодом Python:
# Note the lack of anchors and the use of .fullmatch()
# That method is used here since it is more readable,
# and it automatically adds anchors.
_13_to_20_digits = re.compile('[0-9]{13,20}')
if _13_to_20_digits.fullmatch(text) and len(text) not in (15, 17):
frobnicate()
[нужна цитата]
Во втором шаблоне вы можете заменить начало строки ^
на пользовательский/ограниченный ^(?!(.{15}|.{17})$)
(который создается на основе исключаемой длины). Это обеспечит совпадение каждого начала строки, но только если ее длина не составляет 15 или 17 символов.
Use^(?!(.{15}|.{17})$)[0-9]{13,20}$
instead of^[0-9]{13,20}$
А вот общий код для обработки различных прерывистых диапазонов:
# feel free to adjust the values
(l, r), excep = [13, 20], [15, 17]
to_excl = "|".join(".{%s}" % n for n in excep)
pat = re.compile(r"^(?!(%s)$)[0-9]{%s,%s}$" % (to_excl, l, r))
Тест/выход:
for t in text:
print(
f"{t:<22}", f"{len(t):<4}",
"match" if pat.match(t) else "no-match"
)
01234 5 no-match
012345678901234 15 no-match
0123456789012345 16 match
01234567890123456 17 no-match
012345678901234567 18 match
012345678901234567890 21 no-match
Используемый вход:
from string import digits
s = digits; lens = [5, 15, 16, 17, 18, 21]
text = [s * (l // 10) + s[:l % 10] for l in lens]
['01234',
'012345678901234',
'0123456789012345',
'01234567890123456',
'012345678901234567',
'012345678901234567890']
Похожие вопросы
Новые вопросы
python
Python — это мультипарадигмальный многоцелевой язык программирования с динамической типизацией. Он предназначен для быстрого изучения, понимания и использования, а также обеспечивает чистый и унифицированный синтаксис. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Если у вас есть вопросы о версии Python, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas, NumPy) укажите это в тегах.
^(?!.{15}$)(?!.{17}$)[0-9]{13,20}$
— два отрицательных просмотра отклоняют любую строку одной из запрещенных длин. Я не говорю, что это хороший способ реализовать ваше требование, просто это возможно.^[0-9]{13}([0-9]([0-9][0-9]([0-9][0-9]{1,3})?)?)?$
, но регулярное выражение Джейсона более читабельно