Регулярные выражения (RE, или регулярные выражения, или шаблоны регулярных выражений) — это мощный язык для сопоставления текстовых шаблонов. Возможными примерами шаблонов для поиска являются, например, адреса электронной почты или доменные имена. В этой статье дается базовое введение в регулярные выражения и показано, как регулярные выражения работают в Python. Он будет охватывать все необходимые понятия:

1) Методы поиска совпадений
2) Методы объекта соответствия
3) Метасимволы
4) Дополнительные специальные последовательности
5) Наборы
6) Квантификатор
7) Условия
8) Группировка
9) Примеры
10) Модификация
11) Флаги компиляции

Регулярные выражения внутри Python доступны через модуль `re:

import re

 

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

test_string = '123abc456789abc123ABC'
pattern = re.compile(r'abc')

 

Примечание . Для поиска рекомендуется использовать необработанные строки:

## Use raw strings for the search pattern
a = '\tHello'
b = r'\tHello'
print(a)
print(b)
Hello
    \tHello

 

Выполнение сопоставлений со скомпилированными объектами

Получив шаблон, мы можем искать его в тексте/строке, которую хотим найти.

  • match(): определяет, совпадает ли RE в начале строки.
  • search(): просматривает строку, ища любое место, где это RE соответствует.
  • findall(): находит все подстроки, которым соответствует RE, и возвращает их в виде списка.
  • finditer(): находит все подстроки, которым соответствует RE, и возвращает их как итератор.

Способы модификации

Мы рассмотрим эти методы позже:

  • split(): возвращает список, в котором строка была разделена при каждом совпадении.
  • sub(): заменяет одно или несколько совпадений строкой
# finditer()
my_string = 'abc123ABC123abc'
pattern = re.compile(r'123')
matches = pattern.finditer(my_string)
for match in matches:
    print(match)
    print(match.span(), match.start(), match.end())
    print(match.group()) # returns the string

print()
# findall()
pattern = re.compile(r'123')
matches = pattern.findall(my_string)
for match in matches:
    print(match)

print()
# match
match = pattern.match(my_string)
print(match)
pattern = re.compile(r'abc')
match = pattern.match(my_string)
print(match)

print()
# search
match = pattern.search(my_string)
print(match)
<re.Match object; span=(0, 3), match='123'>
    (0, 3) 0 3
    123
    <re.Match object; span=(15, 18), match='123'>
    (15, 18) 15 18
    123

    123
    123

    None
    <re.Match object; span=(0, 3), match='abc'>

    <re.Match object; span=(0, 3), match='abc'>

 

Примечание. Методы также можно использовать непосредственно в reмодуле. Это не имеет большого значения, но некоторые люди предпочитают явную предварительную компиляцию и привязку шаблона к многократно используемой переменной. (См. https://stackoverflow.com/questions/452104/is-it-worth-using-pythons-re-compile)

matches = re.finditer(r'abc', test_string)
for match in matches:
    print(match)
<re.Match object; span=(3, 6), match='abc'>
   <re.Match object; span=(12, 15), match='abc'>

 

Методы объекта Match

  • group(): возвращает строку, соответствующую RE
  • start(): возвращает начальную позицию совпадения
  • end(): возвращает конечную позицию совпадения
  • span(): возвращает кортеж, содержащий (начальную, конечную) позиции совпадения.
test_string = '123abc456789abc123ABC'
pattern = re.compile(r'abc')
matches = pattern.finditer(test_string)
for match in matches:
    print(match)
    print(match.span(), match.start(), match.end())
    print(match.group()) # returns the substring that was matched by the RE
<re.Match object; span=(3, 6), match='abc'>
    (3, 6) 3 6
    abc
    <re.Match object; span=(12, 15), match='abc'>
    (12, 15) 12 15
    abc

 

Мета персонажи

Метасимволы — это символы со специальным значением:
Все метасимволы: . ^ $ * + ? { } [ ] \ | ( )
Метасимволы должны быть экранированы (с помощью ), если мы действительно хотим искать char.

  • . Любой символ (кроме символа новой строки) «he..o»
  • ^ Начинается с «^ привет»
  • \$ Заканчивается на «мир\$»
  • * Ноль или более вхождений «aix*»
  • + Одно или несколько вхождений «aix+»
  • { } Ровно указанное количество вхождений «al{2}»
  • [] Набор символов «[ам]»
  • \ Обозначает специальную последовательность (может также использоваться для экранирования специальных символов) «\d»
  • | Либо, либо «падает|остается»
  • ( ) Захват и группировка
test_string = 'python-engineer.com'
pattern = re.compile(r'\.')
matches = pattern.finditer(test_string)
for match in matches:
    print(match)
<re.Match object; span=(15, 16), match='.'>

 

Дополнительные метасимволы/специальные последовательности

Специальная последовательность — это символ \, за которым следует один из символов в списке ниже, и он имеет особое значение:

  • \d: соответствует любой десятичной цифре; это эквивалентно классу [0-9].
  • \D: соответствует любому нецифровому символу; это эквивалентно классу [^0-9].
  • \s : соответствует любому пробельному символу;
  • \S : соответствует любому непробельному символу;
  • \w : соответствует любому буквенно-цифровому (словному) символу; это эквивалентно классу [a-zA-Z0-9_].
  • \W : соответствует любому небуквенно-цифровому символу; это эквивалентно классу [^a-zA-Z0-9_].
  • \b Возвращает совпадение, в котором указанные символы находятся в начале или в конце слова r»\bain» r»ain\b»
  • \B Возвращает совпадение, в котором присутствуют указанные символы, но НЕ в начале (или в конце) слова r»\Bain» r»ain\B»
  • \A Возвращает совпадение, если указанные символы находятся в начале строки «\AThe»
  • \Z Возвращает совпадение, если указанные символы находятся в конце строки «Испания\Z»
test_string = 'hello 123_ heyho hohey'
pattern = re.compile(r'\d')
matches = pattern.finditer(test_string)
for match in matches:
    print(match)

print()
pattern = re.compile(r'\s')
matches = pattern.finditer(test_string)
for match in matches:
    print(match)

print()
pattern = re.compile(r'\w')
matches = pattern.finditer(test_string)
for match in matches:
    print(match)

print()
pattern = re.compile(r'\bhey')
matches = pattern.finditer('heyho hohey') # ho-hey, ho\nhey are matches!
for match in matches:
    print(match)

print()
pattern = re.compile(r'\Ahello')
matches = pattern.finditer(test_string)
for match in matches:
    print(match)

print()
pattern = re.compile(r'123_\Z')
matches = pattern.finditer(test_string)
for match in matches:
    print(match)
<re.Match object; span=(6, 7), match='1'>
    <re.Match object; span=(7, 8), match='2'>
    <re.Match object; span=(8, 9), match='3'>

    <re.Match object; span=(5, 6), match=' '>
    <re.Match object; span=(10, 11), match=' '>
    <re.Match object; span=(16, 17), match=' '>

    <re.Match object; span=(0, 1), match='h'>
    <re.Match object; span=(1, 2), match='e'>
    <re.Match object; span=(2, 3), match='l'>
    <re.Match object; span=(3, 4), match='l'>
    <re.Match object; span=(4, 5), match='o'>
    <re.Match object; span=(6, 7), match='1'>
    <re.Match object; span=(7, 8), match='2'>
    <re.Match object; span=(8, 9), match='3'>
    <re.Match object; span=(9, 10), match='_'>
    <re.Match object; span=(11, 12), match='h'>
    <re.Match object; span=(12, 13), match='e'>
    <re.Match object; span=(13, 14), match='y'>
    <re.Match object; span=(14, 15), match='h'>
    <re.Match object; span=(15, 16), match='o'>
    <re.Match object; span=(17, 18), match='h'>
    <re.Match object; span=(18, 19), match='o'>
    <re.Match object; span=(19, 20), match='h'>
    <re.Match object; span=(20, 21), match='e'>
    <re.Match object; span=(21, 22), match='y'>

    <re.Match object; span=(0, 3), match='hey'>

    <re.Match object; span=(0, 5), match='hello'>

 

Наборы

Набор — это набор символов внутри пары квадратных скобок [] со специальным значением. Добавьте несколько условий подряд, например [aA-Z].
^ (знак вставки) внутри множества отменяет выражение.
— (дефис) в наборе указывает диапазон, если он находится между ними, в противном случае сам тире.

Примеры:
— [arn] Возвращает совпадение, в котором присутствует один из указанных символов (a, r или n)
— [an] Возвращает совпадение для любого символа нижнего регистра в алфавитном порядке между a и n
— [^arn] Возвращает совпадение для любого символа, ЗА ИСКЛЮЧЕНИЕМ a, r и n
— [0123] Возвращает совпадение, в котором присутствует любая из указанных цифр (0, 1, 2 или 3)
— [0-9] Возвращает совпадение для любой цифры между 0 и 9
— [0-5][0-9] Возвращает совпадение для любых двузначных чисел от 00 до 59
— [a-zA-Z] Возвращает совпадение для любого символа в алфавитном порядке между a и z, в нижнем регистре ИЛИ верхнем регистре кейс

test_string = 'hello 123_'
pattern = re.compile(r'[a-z]')
matches = pattern.finditer(test_string)
for match in matches:
    print(match)
<re.Match object; span=(0, 1), match='h'>
    <re.Match object; span=(1, 2), match='e'>
    <re.Match object; span=(2, 3), match='l'>
    <re.Match object; span=(3, 4), match='l'>
    <re.Match object; span=(4, 5), match='o'>
dates = '''
01.04.2020

2020.04.01

2020-04-01
2020-05-23
2020-06-11
2020-07-11
2020-08-11

2020/04/02

2020_04_04
2020_04_04
'''

print('all dates with a character in between')
pattern = re.compile(r'\d\d\d\d.\d\d.\d\d')
matches = pattern.finditer(dates)
for match in matches:
    print(match)
print()

print('only dates with - or . in between')
pattern = re.compile(r'\d\d\d\d[-.]\d\d[-.]\d\d') #  no escape for the . here in the set
matches = pattern.finditer(dates)
for match in matches:
    print(match)

print()
print('only dates with - or . in between in May or June')
pattern = re.compile(r'\d\d\d\d[-.]0[56][-.]\d\d')
matches = pattern.finditer(dates)
for match in matches:
    print(match)

# a dash in a character set specifies a range if it is in between, otherwise the dash itself
print()
print('only dates with - or . in between in May, June, July')
pattern = re.compile(r'\d\d\d\d[-.]0[5-7][-.]\d\d') #  no escape for the . here in the set
matches = pattern.finditer(dates)
for match in matches:
    print(match)
all dates with a character in between
    <re.Match object; span=(13, 23), match='2020.04.01'>
    <re.Match object; span=(25, 35), match='2020-04-01'>
    <re.Match object; span=(36, 46), match='2020-05-23'>
    <re.Match object; span=(47, 57), match='2020-06-11'>
    <re.Match object; span=(58, 68), match='2020-07-11'>
    <re.Match object; span=(69, 79), match='2020-08-11'>
    <re.Match object; span=(81, 91), match='2020/04/02'>
    <re.Match object; span=(93, 103), match='2020_04_04'>
    <re.Match object; span=(104, 114), match='2020_04_04'>

    only dates with - or . in between
    <re.Match object; span=(13, 23), match='2020.04.01'>
    <re.Match object; span=(25, 35), match='2020-04-01'>
    <re.Match object; span=(36, 46), match='2020-05-23'>
    <re.Match object; span=(47, 57), match='2020-06-11'>
    <re.Match object; span=(58, 68), match='2020-07-11'>
    <re.Match object; span=(69, 79), match='2020-08-11'>

    only dates with - or . in between in May or June
    <re.Match object; span=(36, 46), match='2020-05-23'>
    <re.Match object; span=(47, 57), match='2020-06-11'>

    only dates with - or . in between in May, June, July
    <re.Match object; span=(36, 46), match='2020-05-23'>
    <re.Match object; span=(47, 57), match='2020-06-11'>
    <re.Match object; span=(58, 68), match='2020-07-11'>

 

Квантификатор

  • * : 0 или больше
  • + : 1 или более
  • ? : 0 или 1, используется, когда символ может быть необязательным.
  • {4} : точное число
  • {4,6} : номера диапазонов (мин., макс.)
my_string = 'hello_123'
pattern = re.compile(r'\d*')
matches = pattern.finditer(my_string)
for match in matches:
    print(match)

print()
pattern = re.compile(r'\d+')
matches = pattern.finditer(my_string)
for match in matches:
    print(match)

print()
my_string = 'hello_1_2-3'
pattern = re.compile(r'_?\d')
matches = pattern.finditer(my_string)
for match in matches:
    print(match)

print()
my_string = '2020-04-01'
pattern = re.compile(r'\d{4}') # or if you need a range r'\d{3,5}'
matches = pattern.finditer(my_string)
for match in matches:
    print(match)
<re.Match object; span=(0, 0), match=''>
    <re.Match object; span=(1, 1), match=''>
    <re.Match object; span=(2, 2), match=''>
    <re.Match object; span=(3, 3), match=''>
    <re.Match object; span=(4, 4), match=''>
    <re.Match object; span=(5, 5), match=''>
    <re.Match object; span=(6, 9), match='123'>
    <re.Match object; span=(9, 9), match=''>

    <re.Match object; span=(6, 9), match='123'>

    <re.Match object; span=(5, 7), match='_1'>
    <re.Match object; span=(7, 9), match='_2'>
    <re.Match object; span=(10, 11), match='3'>

    <re.Match object; span=(0, 4), match='2020'>
dates = '''
2020.04.01

2020-04-01
2020-05-23
2020-06-11
2020-07-11
2020-08-11

2020/04/02

2020_04_04
2020_04_04
'''
pattern = re.compile(r'\d{4}.\d{2}.\d{2}')
matches = pattern.finditer(dates)
for match in matches:
    print(match)
print()

pattern = re.compile(r'\d+.\d+.\d+')
matches = pattern.finditer(dates)
for match in matches:
    print(match)

<re.Match object; span=(1, 11), match='2020.04.01'>
    <re.Match object; span=(13, 23), match='2020-04-01'>
    <re.Match object; span=(24, 34), match='2020-05-23'>
    <re.Match object; span=(35, 45), match='2020-06-11'>
    <re.Match object; span=(46, 56), match='2020-07-11'>
    <re.Match object; span=(57, 67), match='2020-08-11'>
    <re.Match object; span=(69, 79), match='2020/04/02'>
    <re.Match object; span=(81, 91), match='2020_04_04'>
    <re.Match object; span=(92, 102), match='2020_04_04'>

    <re.Match object; span=(1, 11), match='2020.04.01'>
    <re.Match object; span=(13, 23), match='2020-04-01'>
    <re.Match object; span=(24, 34), match='2020-05-23'>
    <re.Match object; span=(35, 45), match='2020-06-11'>
    <re.Match object; span=(46, 56), match='2020-07-11'>
    <re.Match object; span=(57, 67), match='2020-08-11'>
    <re.Match object; span=(69, 79), match='2020/04/02'>
    <re.Match object; span=(81, 91), match='2020_04_04'>
    <re.Match object; span=(92, 102), match='2020_04_04'>

 

Условия

Используйте | для любого или условия.

my_string = """
Mr Simpson
Mrs Simpson
Mr. Brown
Ms Smith
Mr. T
"""
pattern = re.compile(r'Mr\.?\s\w+')
matches = pattern.finditer(my_string)
for match in matches:
    print(match)

print()
pattern = re.compile(r'(Mr|Ms|Mrs)\.?\s\w+')
matches = pattern.finditer(my_string)
for match in matches:
    print(match)
<re.Match object; span=(1, 11), match='Mr Simpson'>
    <re.Match object; span=(24, 33), match='Mr. Brown'>
    <re.Match object; span=(43, 48), match='Mr. T'>

    <re.Match object; span=(1, 11), match='Mr Simpson'>
    <re.Match object; span=(12, 23), match='Mrs Simpson'>
    <re.Match object; span=(24, 33), match='Mr. Brown'>
    <re.Match object; span=(34, 42), match='Ms Smith'>
    <re.Match object; span=(43, 48), match='Mr. T'>

 

Группировка

( ) используется для группировки подстрок в совпадениях.

emails = """
pythonengineer@gmail.com
Python-engineer@gmx.de
python-engineer123@my-domain.org
"""
pattern = re.compile('[a-zA-Z1-9-]+@[a-zA-Z-]+\.[a-zA-Z]+')
pattern = re.compile('[a-zA-Z1-9-]+@[a-zA-Z-]+\.(com|de)')
pattern = re.compile('([a-zA-Z1-9-]+)@([a-zA-Z-]+)\.([a-zA-Z]+)')
matches = pattern.finditer(emails)
for match in matches:
    print(match)
    print(match.group(0))
    print(match.group(1))
    print(match.group(2))
    print(match.group(3))
<re.Match object; span=(1, 25), match='pythonengineer@gmail.com'>
    pythonengineer@gmail.com
    pythonengineer
    gmail
    com
    <re.Match object; span=(26, 48), match='Python-engineer@gmx.de'>
    Python-engineer@gmx.de
    Python-engineer
    gmx
    de
    <re.Match object; span=(49, 81), match='python-engineer123@my-domain.org'>
    python-engineer123@my-domain.org
    python-engineer123
    my-domain
    org

 

Изменение строк

  • split(): разделить строку на список, разбивая ее везде, где соответствует RE
  • sub(): найти все подстроки, в которых совпадает RE, и заменить их другой строкой.
my_string = 'abc123ABCDEF123abc'
pattern = re.compile(r'123') #  no escape for the . here in the set
matches = pattern.split(my_string)
print(matches)

my_string = "hello world, you are the best world"
pattern = re.compile(r'world')
subbed_string = pattern.sub(r'planet', my_string)
print(subbed_string)
['abc', 'ABCDEF', 'abc']
   hello planet, you are the best planet
urls = """
http://python-engineer.com
https://www.python-engineer.org
http://www.pyeng.net
"""
pattern = re.compile(r'https?://(www\.)?(\w|-)+\.\w+')
pattern = re.compile(r'https?://(www\.)?([a-zA-Z-]+)(\.\w+)')
matches = pattern.finditer(urls)
for match in matches:
    #print(match)
    print(match.group()) # 0
    #print(match.group(1))
    #print(match.group(2))
    print(match.group(3))

# substitute using back references to replace url + domain name
subbed_urls = pattern.sub(r'\2\3', urls)
print(subbed_urls)
http://python-engineer.com
    .com
    https://www.python-engineer.org
    .org
    http://www.pyeng.net
    .net

    python-engineer.com
    python-engineer.org
    pyeng.net 

 

Флаги компиляции

  • ASCII, A : делает несколько escape-символов, таких как \w, \b, \s и \d, совпадающими только с символами ASCII с соответствующим свойством.
  • ДОТАЛЛ, С.: Сделать. соответствует любому символу, включая символы новой строки.
  • IGNORECASE, I : поиск совпадений без учета регистра.
  • LOCALE, L : выполнить сопоставление с учетом локали.
  • MULTILINE, M : Многострочное сопоставление, затрагивающее ^ и $.
  • VERBOSE, X (для «расширенного»): включить подробные RE, которые можно организовать более четко и понятно.
my_string = "Hello World"
pattern = re.compile(r'world', re.IGNORECASE) # No match without I flag
matches = pattern.finditer(my_string)
for match in matches:
    print(match)

my_string = '''
hello
cool
Hello
'''
# line starts with ...
pattern = re.compile(r'^[a-z]', re.MULTILINE) # No match without M flag
matches = pattern.finditer(my_string)
for match in matches:
    print(match)
<re.Match object; span=(6, 11), match='World'>
<re.Match object; span=(1, 2), match='h'>
<re.Match object; span=(7, 8), match='c'>

 


0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии