Регулярные выражения

TODO (добавить в методичку, добавить еще и материал главы):
Марк Саммерфилд "Программирование на Python 3. Подробное руководство"
(Programming in Python 3. A Complete Introduction to the Python Language by Mark Summerfield).
* глава 12. Регулярные выражения
Никогда не разбирайте регулярными выражениями html (xml) файл. Используйте специальные модули.
Регулярные выражения нужны для:
- Проверка (match). Правильно ли пишутся деньги, сначала $ потом число в $123.
- Поиск (find). Найти pet.png, pet.jpg, pet.bmp, pet.jpeg, pet.svg, но не найти carpet.png.
- Поиск и замена (find and replace). Заменить все найденные выше файлы на mypet.png.
- Разбить строку по совпадениям с регулярным выражением. Раньше разбивали по пробелам split(), теперь можем разбить по :, = или по словам.
Если шаблон (что ищем) "а", то совпадение с шаблоном в строке "table" будем обозначать так: "t
able"
Символы
Ищем bomb.
- I have dog. - совпадений нет
- I have bomb
- I have bomb and dog.
- I have bombs and cats.
- Bombey - другой регистр.
Квадратные скобки [ ] - любой из перечисленных
Квадратные скобки - любой из перечисленных символов.
Ищем к[оаи]т
- рыжий кот
- синий кит
- крот - не нашли!!! есть лишняя р.
- закат
- каток
- ракета - не нашли, буквы е нет в множестве [оаи]
^ в квадратных скобках - НЕ совпадает
[^ ] - любой КРОМЕ перечисленных символов.
[^abc] - любой символ, кроме a, b или c.
Ищем к[^оаи]т
- рыжий кот
- синий кит
- крест
- ракета
Тире в квадратных скобках
Чтобы написать "любая арабская цифра" не обязательно писать [0123456789]. Можно короче [0-9]
Тире в квадратных скобках - упорядоченное множество
- [0-9] - цифра
- [a-z] - латинская буква (нижний регистр)
- [a-zA-Z] - латинская буква в нижнем или верхнем регистре
- [_0-9a-zA-Z] - символ _ или цифра или латинская буква.
Символ | Значение |
. | Любой символ кроме перевода строки; ИЛИ любой символ, если используется флаг re.DOTALL; или символу . внутри символьного класса |
\d | [0-9] при re.ASCII или цифра Юникода |
\D | [^0-9] при re.ASCII или НЕцифровой символ Юникода |
\s | [ \t\n\r\f\v] при re.ASCII или пробельный символ Юникода |
\S | [^ \t\n\r\f\v] при re.ASCII или НЕпробельный символ Юникода |
\w | [a-zA-Z0-9_] при re.ASCII или символу "слова" (alphanumeric) Юникода |
\W | [^a-zA-Z0-9_] при re.ASCII или символу "слова" (non-alphanumeric) Юникода |
Квантификатор - сколько раз должно встретиться
Символ | Значение - сколько раз должно войти |
* | 0 или больше |
*? | 0 или больше, нежадный |
+ | 1 или больше |
+? | 1 или больше, нежадный |
? | 0 или 1 |
?? | 0 или 1, нежадный |
{3} | Ровно 3 |
{3,} | 3 или больше |
{3,5} | 3, 4 или 5 |
{3,5}? | 3, 4 или 5, нежадный |
Примеры:
- [0-9]{7} - 7-значное число
- [a-z]{3,4} - 3 или 4 буквенные английские слова, например, cat, ball, но не me или kitty.
- 19\d{2} - год формата 19хх
- [012][0-9]:[0-5][0-9] - время в формате hh:mm. Измените шаблон так, чтобы он допускал время в формате 12:34 и 7:05.
- <img src=["']{1}https?[^"']+["']{1} *>
- подходит:
- dfgd<img src="http://example.ru/logo.png">dfgdfg
- <img src='https://null' >
- не подходит:
- <img src="logo.png">
- <img src="http://bebebe'bebebe">
Жадность
По умолчанию регулярные выражения производят так называемый жадный разбор. Другими словами, ищутся совпадения максимальной длины. Когда мы используем точку, с этим могут возникнуть проблемы. Например, нам нужно выдрать некоторый текст из сотни HTML-страниц примерно такого содержания:
<span>Text <em>text</em> text</span><span>Source: http://eax.me/</span>
Шаблон
даст совпадение
Text <em>text</em> text</span><span>Source: http://eax.me/
Шаблон
даст
первое совпадение
Группировка ( )
(abc){2,4} - подходит "abcabc", "abcabcabc" или "abcabcabcabc"
ИЛИ (| она же "палка")
(кошка|собака)
- Подходит:
- У меня есть кошка.
- собака ест кость
Попробуем искать не только слово "кошка", но и все его варианты в разных падежах:
кошка|кошки|кошке|кошку|кошкой|кошек|кошкам|кошками|кошках
можно короче:
кош(ка|ки|ке|ку|кой|ек|кам|ками|ках)
и еще короче:
кош(ек|к(а|и|е|у|ой|ам|ами|ах))
Якоря
- ^ - начало строки
- $ - конец строки
- ^(кошка|собака)
- кошка хочет курить
- я у мамы кошка
- (кошка|собака)$
- кошка хочет курить
- я у мамы кошка
- ^(кошка|собака)$
- кошка хочет курить
- я у мамы кошка
- кошка
Упражнения
идентификатор С
Состоит из латинских букв, арабских цифр и знака _. Не может начинаться с цифры.
Шестнадцетиричное число
Модуль re - работа с регулярными выражениями
Делаем (компилируем) регулярное выражение
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
Если нужно игнорировать регистр, то не усложняем регулярное выражение, а пишем флаг:
>>> p = re.compile('ab*', re.IGNORECASE)
Пишем
Чтобы писать шаблон с \ используйте raw string notation. (Пригодится еще потом, когда будем писать строки для
LaTEX?)
- '\n' - строка из 1 символа (новой строки)
- r'\n' - строка из 2 символов: \ и n
re.match(pattern, string, flags=0)
Начинается ли строка string с шаблона pattern при выставленных флагах
Возвращает найденную группу, или None, если не было совпадений
#!/usr/bin/python
import re
line = "Cats are smarter than dogs"
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
print("matchObj.group() : ", matchObj.group())
print("matchObj.group(1) : ", matchObj.group(1))
print("matchObj.group(2) : ", matchObj.group(2))
else:
print("No match!!")
Напечатает:
matchObj.group() : Cats are smarter than dogs
matchObj.group(1) : Cats
matchObj.group(2) : smarter
re.search(pattern, string, flags=0)
Ищет в строке string шаблон pattern при выставленных флагах.

match - совпадение с началом строки, search - совпадение с любым местом строки.
#!/usr/bin/python
import re
line = "Cats are smarter than dogs";
searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I)
if searchObj:
print("searchObj.group() : ", searchObj.group())
print("searchObj.group(1) : ", searchObj.group(1))
print("searchObj.group(2) : ", searchObj.group(2))
else:
print("Nothing found!!")
Напечатает:
searchObj.group() : Cats are smarter than dogs
searchObj.group(1) : Cats
searchObj.group(2) : smarter
Разница с match:
#!/usr/bin/python
import re
line = "Cats are smarter than dogs";
matchObj = re.match( r'dogs', line, re.M|re.I)
if matchObj:
print("match --> matchObj.group() : ", matchObj.group())
else:
print("No match!!")
searchObj = re.search( r'dogs', line, re.M|re.I)
if searchObj:
print("search --> searchObj.group() : ", searchObj.group())
else:
print("Nothing found!!")
Напечатает:
No match!!
search --> matchObj.group() : dogs
re.sub(pattern, repl, string, max=0) - поиск и замена
В строке string ищем шаблон pattern и заменяем его на строку repl не более max раз (max=0 - делаем все замены)
#!/usr/bin/python
import re
phone = "2004-959-559 # This is Phone Number"
# Delete Python-style comments
num = re.sub(r'#.*$', "", phone)
print("Phone Num : ", num) # Phone Num : 2004-959-559
# Remove anything other than digits
num = re.sub(r'\D', "", phone)
print("Phone Num : ", num) # Phone Num : 2004959559
Флаги
Можно задать в параметре функции flags
Модификатор | Описание |
re.I | без учета регистра |
re.L | Интерпретирует слова с учетом локали (языка). Влияет на \w \W \b and \B |
re.M | ^ и $ соотвествуют началу и концу линии (а не строки) |
re.S | точка - любой символ, включая \n |
re.U | Интерпретирует буквы согласно юникоду. Влияет на \w, \W, \b, \B |
re.X | Permits "cuter" regular expression syntax. It ignores whitespace (except inside a set [] or when escaped by a backslash) and treats unescaped # as a comment marke |
Можно задать прямо в шаблоне:
Шаблон | Описание |
(?imx) | Temporarily toggles on i, m, or x options within a regular expression. If in parentheses, only that area is affected. |
(?-imx) | Temporarily toggles off i, m, or x options within a regular expression. If in parentheses, only that area is affected. |
(?: re) | Groups regular expressions without remembering matched text. |
(?imx: re) | Temporarily toggles on i, m, or x options within parentheses. |
(?-imx: re) | Temporarily toggles off i, m, or x options within parentheses. |
(?#...) | Comment. |
(?= re) | Specifies position using a pattern. Doesn't have a range. |
(?! re) | Specifies position using pattern negation. Doesn't have a range. |
(?> re) | Matches independent pattern without backtracking. |
Задачи
В странице найти все URL, ведущие на картинки (с расширениями png, jpg, bmp, svg)
Это таг вида
<img src="http://acm.mipt.ru/twiki/pub/TWiki/TWikiDocGraphics/tip.gif"></img>
<img src="http://acm.mipt.ru/twiki/pub/TWiki/TWikiDocGraphics/tip.gif"/>
или с дополнительными атрибутами (они необязательные), например:
<img src="http://acm.mipt.ru/twiki/pub/TWiki/TWikiDocGraphics/tip.gif" alt="info" witdh="50" height=50 />
--
TatyanaDerbysheva - 17 Sep 2017