Искаме да се уверим, че подаденият ни телефонен номер е в следния формат: [02] 5–7 цифри
С други думи:
Например, валидни номера са 02555469, както и 987654.
# 15-минутно
# формат: [02] 5-7 цифри
def validate_phone_str(number):
if '02' == number[:2]:
return validate_phone_str(number[2:])
if all([c.isdigit() for c in number]):
return 5 <= len(number) <= 7
return False
# шаблон, който се търси
def validate_phone_re(number):
return bool(re.search(r'^(02)?\d{5,7}$', number))
re.import re
re.search('pattern', 'Find the pattern...')
Всичко е чудесно, но аз вече съм майстор на регулярните изрази.
За всички вас имаме следната задача:
Да се провери дали дадено число е просто чрез регулярен израз. Разрешени операции са:
re.searchс подходящ шаблон.- Употребата на низа '1'.
- Операторa
*.
def testRun():
samples = "01234567 523456 02789a012 027890012 023456 02023456".split()
for number in samples:
print "%s %s %s" % (number.ljust(10),
str(validate_phone_str(number)).ljust(6),
validate_phone_re(number))
>>> testRun()
01234567 False False
523456 True True
02789a012 False False
027890012 True True
023456 False True
02023456 False True
Хм. Я гледай ти... Къде сбъркахме?
# Грешното ни, 15-минутно решение
def validate_phone_str(number):
if '02' == number[:2]:
return validate_phone_str(number[2:])
if all([c.isdigit() for c in number]):
return 5 <= len(number) <= 7
return False
# Едноминутното решение, работещо коректно.
def validate_phone_re(number):
return bool(re.search(r'^(02)?\d{5,7}$', number))
validate_phone_str().(+359|00359|02)?[0-9]{5,7}?. | ( ) [ ] { } + \ ^ $ * ?.\ пред специален символ го прави неспециален такъв.matcher() — по-късно):
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('m|c|n', 'abcdef') # 'abcdef'
matcher('(ab)|c|e', 'abcdef') # 'abcdef'
matcher('m[a-c]|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.'
rere.search(pattern, string, flags=0)re.match(pattern, string, flags=0)re.findall(pattern, string, flags=0)re.split(pattern, string, maxsplit=0)re.sub(pattern, repl, string, count=0)re.compile(pattern, flags=0)re.I (re.IGNORECASE) — Perform case-insensitive matching.re.L (re.LOCALE) — Make \w, \W, \b, \B, dependent on the current locale.re.M (re.MULTILINE) — "^" matches the beginning of lines as well as the string.re.S (re.DOTALL) — "." matches any character at all, including the newline.re.X (re.VERBOSE) — Ignore whitespace and comments for nicer looking RE's.re.U (re.UNICODE) — Make \w, \W, \b, \B, dependent on the Unicode locale.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:]
help(re)