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

„ Програмиране с Python“, ФМИ

from re import stefan_kanev, nikolay_bachiyski, tocho_tochev, dimitur_dimitrov
15.04.2009 г.

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

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

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

Това означава:
  • Трябва да съдържа само цифри
  • Може да започва с код на населеното място: `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 *.
Решения — по-късно.

Понятия

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

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

Пример

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

Повторения (quantifiers)

Важат за непосредствено предхождащия ги символ/клас/група. Нека го означим с 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...'

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

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'

Символни класове

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

Групи

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

Групи за напреднали

Методи на модула 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:]

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

Още въпроси?