Главная страница

ээдд. Прохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен. Николай Прохоренок Владимир Дронов


Скачать 7.92 Mb.
НазваниеНиколай Прохоренок Владимир Дронов
Дата05.05.2023
Размер7.92 Mb.
Формат файлаpdf
Имя файлаПрохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен.pdf
ТипДокументы
#1111379
страница13 из 83
1   ...   9   10   11   12   13   14   15   16   ...   83
(?:[a-z0-9-]+\.)+[a-z]{2,6}) # Домен """, re.I | re.VERBOSE)
>>> r = p.search(email)
>>> r.group("name") # Название ящика 'test'
>>> r.group("host") # Домен 'mail.ru'
Чтобы внутри шаблона обратиться к именованным фрагментам, используется следующий синтаксис:
(?P=name)
. Для примера получим текст между одинаковыми парными тегами:
>>> s = "Text1Text2Text3"
>>> p = re.compile(r"<(?P[a-z]+)>(.*?)", re.S | re.I)
>>> p.findall(s)
[('b', 'Text1'), ('I', 'Text3')]
Кроме того, внутри круглых скобок могут быть расположены следующие конструкции:

(?#...)
— комментарий. Текст внутри круглых скобок игнорируется;

(?=...)
— положительный просмотр вперед. Выведем все слова, после которых распо- ложена запятая:
>>> s = "text1, text2, text3 text4"
>>> p = re.compile(r"\w+(?=[,])", re.S | re.I)
>>> p.findall(s)
['text1', 'text2']

(?!...)
— отрицательный просмотр вперед. Выведем все слова, после которых нет запятой:
>>> s = "text1, text2, text3 text4"
>>> p = re.compile(r"[a-z]+[0-9](?![,])", re.S | re.I)
>>> p.findall(s)
['text3', 'text4']

(?<=...)
— положительный просмотр назад. Выведем все слова, перед которыми распо- ложена запятая с пробелом:
>>> s = "text1, text2, text3 text4"
>>> p = re.compile(r"(?<=[,][ ])[a-z]+[0-9]", re.S | re.I)
>>> p.findall(s)
['text2', 'text3']

(?
— отрицательный просмотр назад. Выведем все слова, перед которыми распо- ложен пробел, но перед пробелом нет запятой:
>>> s = "text1, text2, text3 text4"
>>> p = re.compile(r"(?
>>> p.findall(s)
['text4']

(?(id или name)шаблон1|шаблон2)
— если группа с номером или названием найдена, то должно выполняться условие из параметра шаблон1
, в противном случае должно выпол-

130
Часть I. Основы языка Python няться условие из параметра шаблон2
. Выведем все слова, которые расположены внутри апострофов. Если перед словом нет апострофа, то в конце слова должна быть запятая:
>>> s = "text1 'text2' 'text3 text4, text5"
>>> p = re.compile(r"(')?([a-z]+[0-9])(?(1)'|,)", re.S | re.I)
>>> p.findall(s)
[("'", 'text2'), ('', 'text4')]

(?aiLmsux)
— позволяет установить опции регулярного выражения. Буквы a
, i
,
L
, m
, s
, u
и x
имеют такое же назначение, что и одноименные модификаторы в функции compile()
В
НИМАНИЕ
!
Начиная с Python 3.6, опции, задаваемые внутри регулярного выражения в круглых скобках, объявлены устаревшими и не рекомендованными к использованию. В будущих версиях
Python их поддержка будет удалена.
Рассмотрим небольшой пример. Предположим, необходимо получить все слова, располо- женные после дефиса, причем перед дефисом и после слов должны следовать пробельные символы:
>>> s = "-word1 -word2 -word3 -word4 -word5"
>>> re.findall(r"\s\-([a-z0-9]+)\s", s, re.S | re.I)
['word2', 'word4']
Как видно из примера, мы получили только два слова вместо пяти. Первое и последнее сло- ва не попали в результат, т. к. расположены в начале и в конце строки. Чтобы эти слова по- пали в результат, необходимо добавить альтернативный выбор
(^|\s)
— для начала строки и
(\s|$)
— для конца строки. Чтобы найденные выражения внутри круглых скобок не по- пали в результат, следует добавить символы
?:
после открывающей скобки:
>>> re.findall(r"(?:^|\s)\-([a-z0-9]+)(?:\s|$)", s, re.S | re.I)
['word1', 'word3', 'word5']
Здесь первое и последнее слова успешно попали в результат. Почему же слова word2
и word4 не попали в список совпадений — ведь перед дефисом есть пробел и после слова есть про- бел? Чтобы понять причину, рассмотрим поиск по шагам. Первое слово успешно попадает в результат, т. к. перед дефисом расположено начало строки и после слова есть пробел. По- сле поиска указатель перемещается, и строка для дальнейшего поиска примет следующий вид:
"-word1 <Указатель>-word2 -word3 -word4 -word5"
Обратите внимание на то, что перед фрагментом
-word2
больше нет пробела, и дефис не расположен в начале строки. Поэтому следующим совпадением окажется слово word3
, и указатель снова будет перемещен:
"-word1 -word2 -word3 <Указатель>-word4 -word5"
Опять перед фрагментом
-word4
нет пробела, и дефис не расположен в начале строки. По- этому следующим совпадением окажется слово word5
, и поиск будет завершен. Таким обра- зом, слова word2
и word4 не попадают в результат, поскольку пробел до фрагмента уже был использован в предыдущем поиске. Чтобы этого избежать, следует воспользоваться поло- жительным просмотром вперед
(?=...)
:
>>> re.findall(r"(?:^|\s)\-([a-z0-9]+)(?=\s|$)", s, re.S | re.I)
['word1', 'word2', 'word3', 'word4', 'word5']

Глава 7. Регулярные выражения
131
В этом примере мы заменили фрагмент
(?:\s|$)
на
(?=\s|$)
. Поэтому все слова успешно попали в список совпадений.
7.2. Поиск первого совпадения с шаблоном
Для поиска первого совпадения с шаблоном предназначены следующие функции и методы:
 match()
— проверяет соответствие с началом строки. Формат метода: match(<Строка>[, <Начальная позиция>[, <Конечная позиция>]])
Если соответствие найдено, возвращается объект
Match
, в противном случае — значение
None
:
>>> import re
>>> p = re.compile(r"[0-9]+")
>>> print("Найдено" if p.match("str123") else "Нет")
Нет
>>> print("Найдено" if p.match("str123", 3) else "Нет")
Найдено
>>> print("Найдено" if p.match("123str") else "Нет")
Найдено
Вместо метода match()
можно воспользоваться функцией match()
. Формат функции: re.match(<Шаблон>, <Строка>[, <Модификатор>])
В параметре
<Шаблон>
указывается строка с регулярным выражением или скомпилиро- ванное регулярное выражение. В параметре
<Модификатор>
можно указать флаги, ис- пользуемые в функции compile()
. Если соответствие найдено, то возвращается объект
Match
, в противном случае — значение
None
:
>>> p = r"[0-9]+"
>>> print("Найдено" if re.match(p, "str123") else "Нет")
Нет
>>> print("Найдено" if re.match(p, "123str") else "Нет")
Найдено
>>> p = re.compile(r"[0-9]+")
>>> print("Найдено" if re.match(p, "123str") else "Нет")
Найдено
 search()
— проверяет соответствие с любой частью строки. Формат метода: search(<Строка>[, <Начальная позиция>[, <Конечная позиция>]])
Если соответствие найдено, возвращается объект
Match
, в противном случае — значение
None
:
>>> p = re.compile(r"[0-9]+")
>>> print("Найдено" if p.search("str123") else "Нет")
Найдено
>>> print("Найдено" if p.search("123str") else "Нет")
Найдено
>>> print("Найдено" if p.search("123str", 3) else "Нет")
Нет
Вместо метода search()
можно воспользоваться функцией search()
. Формат функции: re.search(<Шаблон>, <Строка>[, <Модификатор>])

132
Часть I. Основы языка Python
В параметре
<Шаблон>
указывается строка с регулярным выражением или скомпилиро- ванное регулярное выражение. В параметре
<Модификатор>
можно указать флаги, ис- пользуемые в функции compile()
. Если соответствие найдено, возвращается объект
Match
, в противном случае — значение
None
:
>>> p = r"[0-9]+"
>>> print("Найдено" if re.search(p, "str123") else "Нет")
Найдено
>>> p = re.compile(r"[0-9]+")
>>> print("Найдено" if re.search(p, "str123") else "Нет")
Найдено
 fullmatch()
— выполняет проверку, соответствует ли переданная строка регулярному выражению целиком. Формат метода: fullmatch(<Строка>[, <Начальная позиция>[, <Конечная позиция>]])
Если соответствие найдено, то возвращается объект
Match
, в противном случае — значе- ние
None
:
>>> p = re.compile("[Pp]ython")
>>> print("Найдено" if p.fullmatch("Python") else "Нет")
Найдено
>>> print("Найдено" if p.fullmatch("py") else "Нет")
Нет
>>> print("Найдено" if p.fullmatch("PythonWare") else "Нет")
Нет
>>> print("Найдено" if p.fullmatch("PythonWare", 0, 6) else "Нет")
Найдено
Вместо метода fullmatch()
можно воспользоваться функцией fullmatch()
. Формат функции: re.fullmatch(<Шаблон>, <Строка>[, <Модификатор>])
В параметре
<Шаблон>
указывается строка с регулярным выражением или скомпилиро- ванное регулярное выражение. В параметре
<Модификатор>
можно указать флаги, используемые в функции compile()
. Если строка полностью совпадает с шаблоном, воз- вращается объект
Match
, в противном случае — значение
None
:
>>> p = "[Pp]ython"
>>> print("Найдено" if re.fullmatch(p, "Python") else "Нет")
Найдено
>>> print("Найдено" if re.fullmatch(p, "py") else "Нет")
Нет
В качестве примера переделаем нашу программу суммирования произвольного количества целых чисел, введенных пользователем (см. листинг 4.12), таким образом, чтобы при вводе строки вместо числа программа не завершалась с фатальной ошибкой. Предусмотрим также возможность ввода отрицательных целых чисел (листинг 7.5).
Листинг 7.5. Суммирование произвольного количества чисел
# -*- coding: utf-8 -*- import re print("Введите слово 'stop' для получения результата") summa = 0

Глава 7. Регулярные выражения
133 p = re.compile(r"^[-]?[0-9]+$", re.S) while True: x = input("Введите число: ") if x == "stop": break # Выход из цикла if not p.search(x): print("Необходимо ввести число, а не строку!") continue # Переходим на следующую итерацию цикла x = int(x) # Преобразуем строку в число summa += x print("Сумма чисел равна:", summa) input()
Объект
Match
, возвращаемый методами (функциями) match()
, search()
и fullmatch()
,
име- ет следующие атрибуты и методы:
 re
— ссылка на скомпилированный шаблон, указанный в методах (функциях) match()
, search()
и fullmatch()
. Через эту ссылку доступны следующие атрибуты:
• groups
— количество групп в шаблоне;
• groupindex
словарь с названиями групп и их номерами;
• pattern
— исходная строка с регулярным выражением;
• flags
— комбинация флагов, заданных при создании регулярного выражения в функции compile()
, и флагов, указанных в самом регулярном выражении, в конст- рукции
(?aiLmsux)
;
 string
— значение параметра
<Строка>
в методах (функциях) match()
, search()
и fullmatch()
;
 pos
— значение параметра
<Начальная позиция>
в методах match()
, search()
и fullmatch()
;
 endpos
— значение параметра
<Конечная позиция>
в методах match()
, search()
и fullmatch()
;
 lastindex
— возвращает номер последней группы или значение
None
, если поиск завер- шился неудачей;
 lastgroup
— возвращает название последней группы или значение
None
, если эта группа не имеет имени или поиск завершился неудачей:
>>> p = re.compile(r"(?P[0-9]+)(?P[a-z]+)")
>>> m = p.search("123456string 67890text")
>>> m
<_sre.SRE_Match object at 0x00FC9DE8>
>>> m.re.groups, m.re.groupindex
(2, {'num': 1, 'str': 2})
>>> p.groups, p.groupindex
(2, {'num': 1, 'str': 2})
>>> m.string
'123456string 67890text'
>>> m.lastindex, m.lastgroup
(2, 'str')
>>> m.pos, m.endpos
(0, 22)

134
Часть I. Основы языка Python
 group([[, ..., ]])
— возвращает фрагменты, соответ- ствующие шаблону. Если параметр не задан или указано значение
0
, возвращается фрагмент, полностью соответствующий шаблону. Если указан номер или название груп- пы, возвращается фрагмент, совпадающий с этой группой. Через запятую можно указать несколько номеров или названий групп — в этом случае возвращается кортеж, содер- жащий фрагменты, что соответствует группам. Если нет группы с указанным номером или названием, то возбуждается исключение
IndexError
:
>>> p = re.compile(r"(?P[0-9]+)(?P[a-z]+)")
>>> m = p.search("123456string 67890text")
>>> m.group(), m.group(0) # Полное соответствие шаблону
('123456string', '123456string')
>>> m.group(1), m.group(2) # Обращение по индексу
('123456', 'string')
>>> m.group("num"), m.group("str") # Обращение по названию
('123456', 'string')
>>> m.group(1, 2), m.group("num", "str") # Несколько параметров
(('123456', 'string'), ('123456', 'string'))
 groupdict([<Значение по умолчанию>])
— возвращает словарь, содержащий значения именованных групп. С помощью необязательного параметра можно указать значение, которое будет выводиться вместо значения
None для групп, не имеющих совпадений:
>>> p = re.compile(r"(?P[0-9]+)(?P[a-z])?")
>>> m = p.search("123456")
>>> m.groupdict()
{'num': '123456', 'str': None}
>>> m.groupdict("")
{'num': '123456', 'str': ''}
 groups([<Значение по умолчанию>])
— возвращает кортеж, содержащий значения всех групп. С помощью необязательного параметра можно указать значение, которое будет выводиться вместо значения
None для групп, не имеющих совпадений:
>>> p = re.compile(r"(?P[0-9]+)(?P[a-z])?")
>>> m = p.search("123456")
>>> m.groups()
('123456', None)
>>> m.groups("")
('123456', '')
 start([<Номер или название группы>])
— возвращает индекс начала фрагмента, соот- ветствующего заданной группе. Если параметр не указан, то фрагментом является пол- ное соответствие с шаблоном. Если соответствия нет, возвращается значение
-1
;
 end([<Номер или название группы>])
— возвращает индекс конца фрагмента, соответ- ствующего заданной группе. Если параметр не указан, то фрагментом является полное соответствие с шаблоном. Если соответствия нет, возвращается значение
-1
;
 span([<Номер или название группы>])
— возвращает кортеж, содержащий начальный и конечный индексы фрагмента, соответствующего заданной группе. Если параметр не указан, то фрагментом является полное соответствие с шаблоном. Если соответствия нет, возвращается значение
(–1, -1)
:

Глава 7. Регулярные выражения
135
>>> p = re.compile(r"(?P[0-9]+)(?P[a-z]+)")
>>> s = "str123456str"
>>> m = p.search(s)
>>> m.start(), m.end(), m.span()
(3, 12, (3, 12))
>>> m.start(1), m.end(1), m.start("num"), m.end("num")
(3, 9, 3, 9)
>>> m.start(2), m.end(2), m.start("str"), m.end("str")
(9, 12, 9, 12)
>>> m.span(1), m.span("num"), m.span(2), m.span("str")
((3, 9), (3, 9), (9, 12), (9, 12))
>>> s[m.start(1):m.end(1)], s[m.start(2):m.end(2)]
('123456', 'str')
 expand(<Шаблон>)
— производит замену в строке. Внутри указанного шаблона можно использовать обратные ссылки:
\номер группы
,
\g<номер группы>
и
\g<название группы>
Для примера поменяем два тега местами:
>>> p = re.compile(r"<(?P[a-z]+)><(?P[a-z]+)>")
>>> m = p.search("
1   ...   9   10   11   12   13   14   15   16   ...   83


написать администратору сайта