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

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

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

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

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

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

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

         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 pattern.'
         >>> matcher('#', 'What ###?')
         'What ###?'
    

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

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

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

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

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

Примери

         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...'
    

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

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

        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'
    

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

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

Предефинирани класове

Примери за употреба на класове

         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.');
        '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.'
    

Групи за напреднали (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:]
    

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

XKCD

Още въпроси?