8. Регулярни изрази

8. Регулярни изрази

8. Регулярни изрази

14 април 2014

За какво ще си говорим днес

Проблематика

Работа с низове:

Примерни проблеми -- много

Това означава:

Вариант за решение

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))

Преди това, обещаната задачка

Всичко е чудесно, но аз вече съм майстор на регулярните изрази.

За всички вас имаме следната задача:

Да се провери дали дадено число е просто чрез един ред пайтън-код и регулярен израз. Разрешени са

Решения по-късно

Понятия

Регулярните изрази в контекста на Пайтън

Задаване на шаблон

Нашата помощна функция matcher

Пример

>>> matcher('pat', 'Find a pattern.')
'Find a (pat)tern.'
>>> matcher('#', 'What ###?')
'What (#)##?'

Магия от level 1 -- Повторения (quantifiers)

Важат за непосредствено предхождащия ги символ/клас/група. Нека го означим с s.

Примери

matcher('o+', 'Goooooooogle')           # 'G(oooooooo)gle'
matcher('[hH]o+', 'Hohohoho...')        # '(Ho)hohoho...'
# Хм. Не искахме точно това. По-скоро:
matcher('([hH]o)+', 'Hohohoho...')      # '(Hohohoho)...'
matcher('([hH]o){2,3}', 'Hohohoho...')  # '(Hohoho)ho...'

Примери

По подразбиране - алчно търсене за съвпадение (greedy). Деактивира се с ? след квантора.

matcher('[hH]o+', 'Hoooooohohooo...')   # '(Hoooooo)hohooo...'
matcher('[hH]o+?', 'Hoooooohohooo...')  # '(Ho)ooooohohooo...'

Скоби и групиране

Символите ( и ) се използват за логическо групиране на части от шаблона с цел:

Повече за групите -- след малко.

Значения на специалните символи

Значения на специалните символи

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')     # '(ab)cdef'
matcher('am|c|e', 'abcdef')     # 'ab(c)def'
matcher('a(m)|c|e', 'abcdef')   # 'ab(c)def'

Магия от level 2 (DRY) -- Символни класове

>>> matcher('[aeoui]', 'Google')
'G(o)ogle'
matcher('[^CBL][aeoui]', 'Cobol')  # 'Co(bo)l'
>>> matcher('[0-9]{1,3}-[a-z]', 'Figure 42-b')
'Figure (42-b)'
>>> matcher('[^a-zA-Z-]', 'Figure-42-b')
'Figure-(4)2-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'

Gandalf The Gray -- Групи

matcher(r'(\w+).*\1', 'Matches str if str repeats one of its words.');
'M(atches str if str repeat)s 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.'

Групи за напреднали (Gandalf The White)

Методи на модула re

Методи на модула re (2)

MatchObject

Флагове

Кодът на 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:]

На финалната права...

Въпроси?