Работа с низове:
Това означава:
- Трябва да съдържа само цифри
- Може да започва с код на населеното място: `02`, `032` или `052`
- След кода, дължината му може да е между 5 и 7 цифри
- Самият номер (след кода) не може да започва с 0, 1, 2, 3 или 4
def validate_phone_str(number):
if '02' == number[:2]:
return validate_phone_str(number[2:])
elif number[:3] in {'032', '052'}:
return validate_phone_str(number[3:])
if all([c.isdigit() for c in number]):
return 5 <= len(number) <= 7
return False
def validate_phone_re(number):
pattern = r'^(02|032|052)?[5-9]\d{4,6}$'
return bool(re.search(pattern, number))
Да се провери дали дадено число е просто чрез един ред пайтън-код и регулярен израз. Разрешени операции са:
- Самото число, разбира се.
re.search
с подходящ шаблон.- Употребата на низа '1'.
- Операторa
*
.
Решения — по-късно.
import re
— модулът, реализиращ PCRE-функционалността\
r'\s+'
. | ( ) [ ] { } + \ ^ $ * ?
\
пред специален символ го прави неспециален такъв. matcher
matcher()
.matcher(pattern, string)
.>>> matcher('pat', 'Find a pattern.')
'Find a pattern.'
>>> matcher('#', 'What ###?')
'What ###?'
Важат за непосредствено предхождащия ги символ/клас/група. Нека го означим с s
.
s*
означава нула или повече повторения на s
. s+
търси едно или повече повторения на s
. s?
съвпада с нула или едно повторение на s
. s{m,n}
означава между m
и n
повторения на s
, където можем да пропуснем m
или n
. s{,n}
има смисъл на
нула до n
повторения, а s{m,}
— поне m
повторения.`
Символите (
и )
се използват за логическо групиране на части от шаблона с цел:
Повече за групите — след малко.
matcher('o+', 'Goooooooogle') # 'Goooooooogle'
matcher('[hH]o+', 'Hohohoho...') # 'Hohohoho...'
# Хм. Не искахме точно това. По-скоро:
matcher('([hH]o)+', 'Hohohoho...') # 'Hohohoho...'
matcher('([hH]o){2,3}', 'Hohohoho...') # 'Hohohoho...'
По подразбиране — алчно търсене за съвпадение (greedy). Деактивира се с `?` след квантора.
matcher('[hH]o+', 'Hoooooohohooo...') # 'Hoooooohohooo...'
matcher('[hH]o+?', 'Hoooooohohooo...') # 'Hoooooohohooo...'
.
съвпада с един произволен символ. По подразбиране символите за нов ред не се включват в тази група. ^
съвпада с началото на низ (или на ред, ако се работи в MULTILINE режим.) $
съвпада с края на низ (или на ред, ако се работи в MULTILINE режим.) |
има смисъл на или, например:matcher('day|nice', 'A nice dance-day.') # 'A nice dance-day.'
matcher('da(y|n)ce', 'A nice dance-day.') # 'A nice dance-day.'
NB! Единствено |
се прилага не над непосредствените му символи/класове, а на целия низ отляво/отдясно:
matcher('ab|c|e', 'abcdef') # 'abcdef'
matcher('am|c|e', 'abcdef') # 'abcdef'
matcher('a(m)|c|e', 'abcdef') # 'abcdef'
[
и ]
, например [aeoui]
. >>> matcher('[aeoui]', 'Google')
'Google'
^
в началото на класа:matcher('[^CBL][aeoui]', 'Cobol') # 'Cobol'
>>> matcher('[0-9]{1,3}-[a-z]', 'Figure 42-b')
'Figure 42-b'
>>> matcher('[^a-zA-Z-]', 'Figure-42-b')
'Figure-42-b'
\d
— една цифра; същото като [0-9]
. \D
— един символ, който не е цифра; същото като [^0-9]
. \s
— един whitespace символ — [\t\r\n\f\v]
. \S
— един символ, който не е whitespace — [^\t\r\n\f\v]
. \w
— една буква или цифра. \W
— един символ, който не е буква или цифра. \b
— нула символа, но граница на дума. matcher(r'\d+', 'Phone number: 5551234')
# 'Phone number: 5551234'
matcher(r'\w+', 'Phone number: 5551234')
# 'Phone number: 5551234'
matcher(r'\s+', 'Phone number: 5551234')
# 'Phone number: 5551234'
(
и )
. \1
— първата група, \2
— втората и така нататък. matcher(r'(\w+).*\1', 'Matches str if str repeats one of its words.');
'Matches str if str repeats one of its words.'
# Хм. Не точно. Нека опитаме пак:
matcher(r'(\b\w+\b).*\1', 'Matches str if str repeats one of its words.');
'Matches str if str repeats one of its words.'
(?:…)
— използване на скоби, без да се създава група. (?P…)
— текстът, отговарящ на групата, може да бъде достъпван чрез име, вместо чрез номер. (?P=name)
— търси съвпадение за текста, намерен по-рано от групата, кръстена name
. (?#…)
— коментар, игнорира се. (?=…)
— съвпада, ако … следва, но не го „консумира“ (look-ahead). (?!…)
— съвпада, ако … не следва. (?(id/name)yes|no)
— търси за шаблона 'yes', ако групата с номер/име съвпада, или с (опционалния) шаблон 'no' иначе. help(re)
re
re.search()
— проверява дали даден низ съдържа текст, отговарящ на зададения шаблонre.match()
— същото както горното, само че се търси за съвпадение в началото на низаre.findall()
— връща като списък всички съвпадения на шаблона в дадения низre.finditer()
— същото като горното, но връща итераторre
(2)re.sub(pattern, repl, string, count=0)
— заместване в низ, на база на шаблонre.split(pattern, string, maxsplit=0)
— разделяне на низ на парчета, на база на шаблонre.escape(pattern)
— escape-ва всички специални за регулярен израз символиre.escape('a(a)\s+')
ще върне 'a\\(a\\)\\\\s\\+'
help(re)
MatchObject
group()
— връща частта от низа, отговаряща на шаблона (и още…) start()
— връща началото на съвпадението в низаend()
— връща края на съвпадението в низаspan()
— връща (start, end) под формата на tuplere.I
(re.IGNORECASE) — case-insensitive търсене. re.L
(re.LOCALE) — кара \w, \W, \b, \B да зависят от текущия locale. re.M
(re.MULTILINE) — кара „^“ да съвпада както с начало на низ, така и с начало на ред, докато „$“ ще съвпада с край на ред или края на низа. re.S
(re.DOTALL) — „.“ ще съвпада с всеки символ, включително и нов ред. re.X
(re.VERBOSE) — режим на игнориране на white-space и коментари (за по-дългички RE). re.А
(re.ASCII) — кара \w, \W, \b, \B, \d, \D да отговарят на съответните ASCII-класове. matcher()
def matcher(regex, string):
match = re.search(regex, string)
if match is None: return string
start, end = match.span()
return string[:start]
+ '<<<' + string[start:end] + '>>>' +
string[end:]
'prime' if not re.search(<някакъв шаблон>, '1' * <число>) else 'not prime'
r'^1?$|^(11+?)\1+$'
. Въпроси?