Раздел «Язык Си».PythonRegexp:

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

REFACTOR TODO (добавить в методичку, добавить еще и материал главы):

Марк Саммерфилд "Программирование на Python 3. Подробное руководство"
(Programming in Python 3. A Complete Introduction to the Python Language by Mark Summerfield). * глава 12. Регулярные выражения

IDEA! Никогда не разбирайте регулярными выражениями html (xml) файл. Используйте специальные модули.

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

Если шаблон (что ищем) "а", то совпадение с шаблоном в строке "table" будем обозначать так: "table"

Символы

Ищем bomb.

Квадратные скобки [ ] - любой из перечисленных

Квадратные скобки - любой из перечисленных символов.

Ищем к[оаи]т

^ в квадратных скобках - НЕ совпадает

[^ ] - любой КРОМЕ перечисленных символов.

[^abc] - любой символ, кроме a, b или c.

Ищем к[^оаи]т

Тире в квадратных скобках

Чтобы написать "любая арабская цифра" не обязательно писать [0123456789]. Можно короче [0-9]

Тире в квадратных скобках - упорядоченное множество

Символ Значение
. Любой символ кроме перевода строки; ИЛИ любой символ, если используется флаг 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, нежадный 

Примеры:

Жадность

По умолчанию регулярные выражения производят так называемый жадный разбор. Другими словами, ищутся совпадения максимальной длины. Когда мы используем точку, с этим могут возникнуть проблемы. Например, нам нужно выдрать некоторый текст из сотни HTML-страниц примерно такого содержания:

<span>Text <em>text</em> text</span><span>Source: http://eax.me/</span>

Шаблон

<span>(.*)</span>
даст совпадение
Text <em>text</em> text</span><span>Source: http://eax.me/

Шаблон

<span>(.*?)</span>
даст первое совпадение
Text <em>text</em> text

Группировка ( )

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

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 при выставленных флагах.

IDEA! 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

Attachment sort Action Size Date Who Comment
regexp.pdf manage 95.5 K 17 Sep 2017 - 15:27 TatyanaDerbysheva Шпаргалка по регулярным выражениям