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

Группирующие скобки (…) и match-объекты в питоне

Match-объекты

Если функции , не находят соответствие шаблону в строке, то они возвращают , функция возващает пустой итератор.
Однако если соответствие найдено, то возвращается -объект.
Эта штука содержит в себе кучу полезной информации о соответствии шаблону.
В отличие от предыдущих функций, возвращает «простой и понятный» список соответствий.
Полный набор атрибутов -объекта можно посмотреть в , а здесь приведём самое полезное.

Метод Описание Пример
Подстрока, соответствующая всему шаблону
Индекс в исходной строке, начиная с которого идёт найденная подстрока
Индекс в исходной строке, который следует сразу за найденной подстрока

Группирующие скобки

Если в шаблоне регулярного выражения встречаются скобки без , то они становятся группирующими.
В match-объекте, который возвращают , и , по каждой такой группе можно получить ту же информацию, что и по всему шаблону. А именно часть подстроки, которая соответствует , а также индексы начала и окончания в исходной строке. Достаточно часто это бывает полезно.

import re
pattern = r'\s*(+)(\d+)\s*'
string = r'---   Опять45   ---'
match = re.search(pattern, string)
print(f'Найдена подстрока >{match.group(0)}< с позиции {match.start(0)} до {match.end(0)}')
print(f'Группа букв >{match.group(1)}< с позиции {match.start(1)} до {match.end(1)}')
print(f'Группа цифр >{match.group(2)}< с позиции {match.start(2)} до {match.end(2)}')
###
# Найдена подстрока >   Опять45   < с позиции 3 до 16
# Группа букв >Опять< с позиции 6 до 11
# Группа цифр >45< с позиции 11 до 13

Тонкости со скобками и нумерацией групп.

Если к группирующим скобкам применён квантификатор (то есть указано число повторений), то подгруппа в match-объекте будет создана только для последнего соответствия.
Например, если бы в примере выше квантификаторы были снаружи от скобок , то вывод был бы таким:

Найдена подстрока >   Опять45   < с позиции 3 до 16
Группа букв >ь< с позиции 10 до 11
Группа цифр >5< с позиции 12 до 13

Внутри группирующих скобок могут быть и другие группирующие скобки.
В этом случае их нумерация производится в соответствии с номером появления открывающей скобки с шаблоне.

import re
pattern = r'((\d)(\d))((\d)(\d))'
string = r'123456789'
match = re.search(pattern, string)
print(f'Найдена подстрока >{match.group(0)}< с позиции {match.start(0)} до {match.end(0)}')
for i in range(1, match.groups()+1):
    print(f'Группа №{i} >{match.group(i)}< с позиции {match.start(i)} до {match.end(i)}')
###
Найдена подстрока >1234< с позиции 0 до 4
Группа №1 >12< с позиции 0 до 2
Группа №2 >1< с позиции 0 до 1
Группа №3 >2< с позиции 1 до 2
Группа №4 >34< с позиции 2 до 4
Группа №5 >3< с позиции 2 до 3
Группа №6 >4< с позиции 3 до 4

Группы и

Если в шаблоне есть группирующие скобки, то вместо списка найденных подстрок будет возвращён список кортежей, в каждом из которых только соответствие каждой группе. Это не всегда происходит по плану, поэтому обычно нужно использовать негруппирующие скобки .

import re
print(re.findall(r'(+)(\d*)', r'foo3, im12, go, 24buz42'))
# -> 

Группы и

Если в шаблоне нет группирующих скобок, то работает очень похожим образом на .
А вот если группирующие скобки в шаблоне есть, то между каждыми разрезанными строками будут все соответствия каждой из подгрупп.

import re
print(re.split(r'(\s*)([+*/-])(\s*)', r'12  +  13*15   - 6'))
# -> 

Regular Expression Objects

If you want to use the same regular expression more than once, you should compile it into a regular expression object. Regular expression objects are more efficient, and make your code more readable. To create one, just call re.compile(regex) or re.compile(regex, flags). The flags are the matching options described above for the re.search() and re.match() functions.

The regular expression object returned by re.compile() provides all the functions that the re module also provides directly: search(), match(), findall(), finditer(), sub() and split(). The difference is that they use the pattern stored in the regex object, and do not take the regex as the first parameter. re.compile(regex).search(subject) is equivalent to re.search(regex, subject).

Match Object

A Match Object is an object containing information
about the search and the result.

Note: If there is no match, the value will be
returned, instead of the Match Object.

Example

Do a search that will return a Match Object:

import retxt = «The rain in Spain»x = re.search(«ai»,
txt)
print(x) #this will print an object

The Match object has properties and methods used to retrieve information
about the search, and the result:

returns a tuple containing the start-, and end positions of the match. returns the string passed into the function returns the part of the string where there was a match

Example

Print the position (start- and end-position) of the first match occurrence.

The regular expression looks for any words that starts with an upper case
«S»:

import re
txt = «The rain in Spain»
x = re.search(r»\bS\w+», txt)
print(x.span())

Example

Print the string passed into the function:

import re
txt = «The rain in Spain»
x = re.search(r»\bS\w+», txt)
print(x.string)

Example

Print the part of the string where there was a match.

The regular expression looks for any words that starts with an upper case
«S»:

import re
txt = «The rain in Spain»
x = re.search(r»\bS\w+», txt)
print(x.group())

Note: If there is no match, the value will be
returned, instead of the Match Object.

re.search

The re.search() method takes a regular expression pattern and a string and
searches for that pattern within the string.

The syntax is re.search(pattern, string).

where:pattern
regular expression to be matched.

string
the string which would be searched to match the pattern anywhere in the string.

It searches for first occurrence of RE pattern within string with optional flags.

If the search is successful, search() returns a match object or None otherwise.

Therefore, the search is usually immediately followed by an if-statement to test
if the search succeeded.

It is common to use the ‘r’ at the start of the pattern string, that designates
a python “raw” string which passes through backslashes without change which is
very handy for regular expressions.

This example searches for the pattern ‘word:’ followed by a 3 letter word.

The code match = re.search(pat, str) stores the search result in a variable
named “match”.

Then the if-statement tests the match, if true the search succeeded and
match.group() is the matching text (e.g. ‘word:cat’).

If the match is false, the search did not succeed, and there is no matching text.

As you can see in the example below, I have used the | operator, which search for either pattern I specify.

The output of above script will be:

Python FOUND
Perl FOUND
PHP FOUND
C++ NOT FOUND

Strings, Backslashes and Regular Expressions

The backslash is a metacharacter in regular expressions, and is used to escape other metacharacters. The regex \\ matches a single backslash. \d is a single token matching a digit.

Python strings also use the backslash to escape characters. The above regexes are written as Python strings as "\\\\" and "\\w". Confusing indeed.

Fortunately, Python also has “raw strings” which do not apply special treatment to backslashes. As raw strings, the above regexes become r"\\" and r"\w". The only limitation of using raw strings is that the delimiter you’re using for the string must not appear in the regular expression, as raw strings do not offer a means to escape it.

You can use \n and \t in raw strings. Though raw strings do not support these escapes, the regular expression engine does. The end result is the same.

Special Sequences

A special sequence is a followed by one of the characters in the list below, and has a special meaning:

Character Description Example Try it
\A Returns a match if the specified characters are at the beginning of the
string
«\AThe» Try it »
\b Returns a match where the specified characters are at the beginning or at the
end of a word(the «r» in the beginning is making sure that the string is
being treated as a «raw string»)
r»\bain»r»ain\b» Try it »Try it »
\B Returns a match where the specified characters are present, but NOT at the beginning
(or at
the end) of a word(the «r» in the beginning is making sure that the string
is being treated as a «raw string»)
r»\Bain»r»ain\B» Try it »Try it »
\d Returns a match where the string contains digits (numbers from 0-9) «\d» Try it »
\D Returns a match where the string DOES NOT contain digits «\D» Try it »
\s Returns a match where the string contains a white space character «\s» Try it »
\S Returns a match where the string DOES NOT contain a white space character «\S» Try it »
\w Returns a match where the string contains any word characters (characters from
a to Z, digits from 0-9, and the underscore _ character)
«\w» Try it »
\W Returns a match where the string DOES NOT contain any word characters «\W» Try it »
\Z Returns a match if the specified characters are at the end of the string «Spain\Z» Try it »

Компилирование

Модуль re позволяет вам «компилировать» выражение, которое вы ищите чаще всего. Это также позволит вам превратить выражение в объект SRE_Pattern. Вы можете использовать этот объект в вашей функции поиска в будущем. Давайте используем код из предыдущего примера и изменим его, чтобы использовать компилирование:

Python

import re

text = «The ants go marching one by one»

strings =

for string in strings:
regex = re.compile(string)
match = re.search(regex, text)
if match:
print(‘Found «{}» in «{}»‘.format(string, text))
text_pos = match.span()
print(text)
else:
print(‘Did not find «{}»‘.format(string))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

importre

text=»The ants go marching one by one»

strings=’the’,’one’

forstringinstrings

regex=re.compile(string)

match=re.search(regex,text)

ifmatch

print(‘Found «{}» in «{}»‘.format(string,text))

text_pos=match.span()

print(textmatch.start()match.end())

else

print(‘Did not find «{}»‘.format(string))

Обратите внимание на то, что здесь мы создаем объект паттерна, вызывая compile в каждой строке нашего списка, и назначаем результат переменной – регулярному выражению. Далее мы передаем это выражение нашей поисковой функции

Остальная часть кода остается неизменной. Основная причина, по которой используют компилирование это сохранить выражение для повторного использования в вашем коде в будущем. В любом случае, компилирование также принимает флаги, которые могут быть использованы для активации различных специальных функций. Мы рассмотрим это далее.
Обратите внимание: когда вы компилируете паттерны, они автоматически кэшируются, так что если вы не особо используете регулярные выражения в своем коде, тогда вам не обязательно сохранять компилированный объект как переменную.

Символьный класс

Часто требуется
найти не одно какое-то конкретное написание слова, а все его множественные
формы, например:

еда, еду, Еда,
Еду

здесь первая
буква может быть малой или заглавной, а последняя или а, или у. Чтобы в нашем
шаблоне охватить все эти варианты используются символьные классы,
которые определяются квадратными скобками:

В нашем случае
его можно использовать так:

text = "Еда, беду, победа"
match = re.findall(r"д", text)

Мы здесь в
первых квадратных скобках указываем, что первым символом может быть е
или Е. Далее, должен идти символ д. А в конце стоять символ а
или у. Благодаря использованию символьного класса будут найдены все
комбинации:

Или, например,
мы хотим определить наличие одной (любой) цифры в нашем тексте. Для этого можно
записать вот такой символьный класс:

text = "Еда, беду, 5 победа"
match = re.findall(r"", text)

и будет найдена
цифра 5. Но, для удобства, в символьном классе можно указывать диапазон
значений:

match = re.findall(r"", text)

Результат будет
тот же. Если нужно инвертировать последовательность символов в символьном
классе, то используется символ ^:

match = re.findall(r"", text)

Данный шаблон означает
поиск любого нецифрового символа. Результатом будет последовательность:

Причем, обратите
внимание, если символ дефиса ‘-‘ записать первым в символьном классе:

text = "Еда, беду, из-за, победа"
match = re.findall(r"", text)

то он будет
соответствовать просто этому символу.

По аналогии
можно задавать интервал и для символов, например, так:

match = re.findall(r"", text)

на выходе
получим найденные малые символы:

Или записывать
несколько диапазонов:

match = re.findall(r"", text)

Будут находиться
все буквы русского алфавита и цифры. Также внутри символьного класса все
специальные символы (кроме обратного слеша ‘\’) теряют свое значение и
воспринимаются как обычные символы:

text = "(еда), еда, победа"
match = re.findall(r"еда", text)

Здесь будет
искаться строка «(еда)», так как круглые скобки записаны в символьном классе. Но
два символа: ^ и — принимают новое значение, как мы только что видели.

Некоторые наборы
символов, например, или и другие довольно часто используются на
практике, поэтому им были назначены специальные краткие формы:

Символ

Значение

Соответствует
любому символу, кроме символа переноса строки (‘\n’). Но, если
установлен флаг re.DOTALL, то точка соответствует вообще
любому символу в тексте. Однако, если она записана внутри символьного класса ,
то воспринимается как символ точки.

\d

Соответствует
любой цифре, если используется кодировка Юникода. Если же установлен флаг re.ASCII, то диапазону
цифр .

\D

Соответствует
любому не цифровому символу для Юникода или символьному классу при
установленном флаге re.ASCII

\s

Для
Юникода – любой пробельный символ. Для re.ASCII – символьному
классу

\S

Для
Юникода – любой не пробельный символ. Для re.ASCII – символьному
классу

\w

Для
Юникода – любой символ слова. При флаге re.ASCII – набору
символов

\W

Для
Юникода – любой не символ слова. При флаге re.ASCII – набору
символов

Например, если
записать вот такой шаблон:

text = "(еда), еда, победа"
match = re.findall(r".", text)

то получим
список из всех символов строки text. Если записать так:

match = re.findall(r"\w", text)

то только
символы слов:

Но, если указать
флаг re.ASCII:

match = re.findall(r"\w", text, re.ASCII)

то получим
пустой список, т.к. символьный класс в этом случае будет иметь вид и в нем
нет символов русского алфавита. Также специальные наборы можно записывать и
внутри символьных классов, например, так:

text = "0xf, 0xa, 0x5"
match = re.findall(r"0x")

Здесь мы
выделяем шестнадцатиричные числа из строки.

Вот что из себя
в самом простом случае представляют регулярные выражения и символьный класс. На
следующем занятии мы продолжим эту тему и рассмотрим новые конструкции языка регулярных
выражений.

Видео по теме

Регулярные выражения #1: литералы и символьный класс

Регулярные выражения #2: квантификаторы {m,n}

Регулярные выражения #3: сохраняющие скобки и группировка

Регулярные выражения #4: флаги и проверки

Регулярные выражения #5: объект re.Match, методы re.search, re.finditer, re.findall

Регулярные выражения #6: методы re.match, re.split, re.sub, re.subn, re.compile

Разность re.match и re.search

re.match соответствует только начало строки, если начало строки не соответствует регулярному выражению, совпадение не найдено, функция возвращает None, и re.search совпадают со строкой, пока не найдет совпадения.

Пример:

#!/usr/bin/python3

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!!")

matchObj = re.search( r'dogs', line, re.M|re.I)
if matchObj:
   print ("search --> matchObj.group() : ", matchObj.group())
else:
   print ("No match!!")
No match!!
search --> matchObj.group() :  dogs

Search and Replace

re.sub(regex, replacement, subject) performs a search-and-replace across subject, replacing all matches of regex in subject with replacement. The result is returned by the sub() function. The subject string you pass is not modified.

If the regex has capturing groups, you can use the text matched by the part of the regex inside the capturing group. To substitute the text from the third group, insert \3 into the replacement string. If you want to use the text of the third group followed by a literal three as the replacement, use \g<3>3. \33 is interpreted as the 33rd group. It is an error if there are fewer than 33 groups. If you used named capturing groups, you can use them in the replacement text with \g<name>.

The re.sub() function applies the same backslash logic to the replacement text as is applied to the regular expression. Therefore, you should use raw strings for the replacement text, as I did in the examples above. The re.sub() function will also interpret \n and \t in raw strings. If you want c:\temp as a replacement, either use r"c:\\temp" or "c:\\\\temp". The 3rd backreference is r"\3" or "\\3".

re.match функция

re.match пытается сопоставить шаблон из исходного положения строки, если не согласующий стартовая позиция является успешным, матч () не возвращает ничего.

Синтаксис функции:

re.match(pattern, string, flags=0)

Параметры функции:

параметры описание
шаблон Матч регулярное выражение
строка Строка для соответствия.
флаги Флаг, регулярное выражение соответствия используется для управления, например: соответствует ли чувствительны к регистру, многострочный, и так далее.

Успешный метод матча re.match возвращает объект соответствия, в противном случае None.

Мы можем использовать эту группу (NUM) или группы () функцию, чтобы получить объекты, соответствующие выражения совпадают.

Соответствующие методы объекта описание
группа (Num = 0) Весь соответствующий строковое выражение, группа () может ввести более одного номера группы, в этом случае он будет возвращать значение, соответствующее этим группам кортежей.
группы () Он возвращает кортеж из всех групп строки, от 1 до количества, содержащегося в группе.

Пример 1:

#!/usr/bin/python
# -*- coding: UTF-8 -*- 

import re
print(re.match('www', 'www.w3big.com').span())  # 在起始位置匹配
print(re.match('com', 'www.w3big.com'))         # 不在起始位置匹配

Запуск в приведенном выше примере выход:

(0, 3)
None

Пример 2:

#!/usr/bin/python3
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
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *