Регулярные выражения: основы составления правил

Продолжим говорить о регулярных выражениях в Python в рамках NLP. Регулярные выражения нужны для поиска подстрок, которые удовлетворяют правилам. Например, нужно найти все слова, которые начинаются с заглавной буквы «А», или все даты в предложении, которое содержит и другие виды чисел. Сегодня мы расскажем об основных символах, которые образуют регулярные выражения: замена, группировка, перечисление символов, а также специальные символы в Python.

Один любой символ или повторять до бесконечности

Когда появляется ситуация, когда мы не знаем какой именно символ используется, то используется точка .. А когда нужно повторить какой символ сколько-то раз, то используется звездочка * (0 или n символов) или плюс + (1 или n символов). Рассмотрите примеры регулярных выражений в Python:

# aa.bb. # Может значить aapbby или aa4bb$
# a.b* # Может значить acbbb или aqb или a,bbbbbb
>>> import re
>>> re.search('aa.bb.', 'aapbby')
<re.Match object; span=(0, 6), match='aapbby'>
>>> re.search('a.b*', 'a,bbbbbb')
<re.Match object; span=(0, 8), match='a,bbbbbb'>

Точка и звездочка могут использоваться вместе .*, тогда это значит любой символ повторяется сколько-то раз. Это удобно, когда вы не помните все выражение, но знаете каким символом он заканчивается. Ниже пример того, как применять такое регулярное выражение в Python.

>>> re.search('<h.*>', '<html>')
<re.Match object; span=(0, 6), match='<html>'>

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

# Вместо <html> совпала вся строка, потому что она оканичается на символ '>'
>>> re.search('<h.*>', '<html>..<li>...</li>')
<re.Match object; span=(0, 20), match='<html>..<li>...</li>'>

Группа символов

Символы могут быть сгруппированы с помощью круглых скобок. К этим группам могут быть применены повторения * или +. Кроме того внутри скобок может использоваться оператор ИЛИ в виде |. Следующие примеры показывают разные регулярные выражения в Python с применением группировок:

# (ac)* # соответсвует acacac или acac
# Знак | соответсвует ИЛИ:
>>> re.search('d(e|i)n', 'den')
<re.Match object; span=(0, 3), match='den'>
>>> re.search('d(e|i)n', 'din')
<re.Match object; span=(0, 3), match='din'>

Перечисление символов

Как мы увидели, использовать .* опасно. Поэтому лучше всего перечислять всевозможные символы внутри квадратных скобок []. Например, не известно какой знак препинания следует дальше, тогда в Python можно регулярное выражение вывести следующим образом:

>>> pattern = 'a[,u]bc'
>>> re.search(pattern, 'a,bc')
<re.Match object; span=(0, 4), match='a,bc'>
>>> re.search(pattern, 'aubc')
<re.Match object; span=(0, 4), match='aubc'>
>>> re.search(pattern, 'adbc') # Ничего не нашел

Последний пример не соответствует правилу, потому что символ 'd' не указан в []. Также в квадратных скобках можно указывать диапазоны букв и цифры. Например, [a-z] означает все строчные буквы английского алфавита, [A-Z] — все прописные, а [0-9] — все цифры. Ниже приведены примеры регулярных выражения с применением диапазонов на Python.

>>> re.search('[a-z0-5]+', 'asaBR')
<re.Match object; span=(0, 3), match='asa'>
>>> re.search('[a-z0-5]+', 'B612')
<re.Match object; span=(2, 4), match='12'>

Также если внутри квадратных скобок указан символ ^, то это значит «всё, что НЕ совпадает». Например, [^0-9] — любой символ не цифра. Диапазоны кириллических символов задаются в виде [А-Яа-я].

Обратный слэш для пропуска символов

Как в квадратных скобках для регулярного выражения указать знак препинания точку? Ведь точка является специальным правилом, которое обозначает «любой символ». Для таких случаев используется обратный слэш \. При использовании перед специальными символами Python интерпретирует их как обычные символы. Поэтому чтобы пропустить также сами квадратные скобки, то и перед ними тоже нужно его поставить. Ниже показаны примеры регулярных выражения с использованием обратного слэша на Python.

>>> pattern = 'a[,\.\]]bc' # Это , или . или ]
>>> re.search(pattern, r'a]bc')
<re.Match object; span=(0, 4), match='a]bc'>
 >>> re.search(pattern, r'a.bc')
<re.Match object; span=(0, 4), match='a.bc'>

В строке обратный слэш тоже имеет особое значение. Он ответственен за специальные символы: \n (новая строка), \t (отступ), \s (пробел) и т.д. Их так же можно перечислять в квадратных скобках. А вот для пропуска самого обратного слэша в Python, требуется повторить его 4 раза. Ведь два слэша значат слэш как обычный символ, а чтобы пропустить его нужно два обычных. Иными словами, это:

>>> re.search('\\\\', 'ab\cd')
<re.Match object; span=(2, 3), match='\\'>

интерпретируется как это:

regex("\\" [пропущенный слэш] пропускает "\\" [пропущенный слэш])

В Python строку можно инициализировать как raw (сырую), т.е. в ней обратный слэш будет считаться как обычный символ. Для этого перед строкой указывается r. Взгляните как прописываются пути Windows в Python в виде обычной и сырой строки:

>>> 'C:\User\admin\python'
  File "<stdin>", line 1
    'C:\User\admin\python'
SyntaxError: (unicode error) 'unicodeescape' codec can t decode bytes in position 2-3: truncated \UXXXXXXXX escape
SyntaxError: invalid syntax
# Ошибка, потому что Python не понимает \U
# Чтобы прописать путь, используется \\ или r:
>>> path = 'C:\\User\\admin\\python'
>>> raw_path = r'C:\\User\\admin\\python'

Цифры, пробелы, отступы

Использование обратного слэша вместе с некоторыми символами даст новое значение строке. Так, \n — новая строка, \t — отступ . Есть ещё полезные специальные символы:

  • \d — любая цифра, эквивалентно использованию [0-9]
  • \D — любая не цифра, эквивалентно использованию [^0-9]
  • \s — пробел
  • \s — не пробел
  • \w — любой цифробуквенный символ, эквивалентно использованию [a-zA-Z0-9_]
  • \W — любой не цифробуквенный символ, эквивалентно использованию [^a-zA-Z0-9_]
>>> re.search('\d\d\d\d-\d\d-\d\d', '2020-05-10')
<re.Match object; span=(0, 10), match='2020-05-10'>

Этот пример на Python показывает, как можно найти даты в предложении с применением специальных символов. Ниже таблица, в который приведены символы для регулярных выражений.

Символ Значение Пример Совпадения
. Любой одиночный символ (включая числа, пробелы и т. д.). f.t fat, fit, fet
* Повторение 0 или более раз a*b* aabbb, bbb, ab, aaa
+ Повторение 1 или более раз a+b+ aabbb, ab, aaabbb
[] Выбор любого символа в скобках [a-z]* apes, banana, flu
[^] Любой символ, которого нет в скобках [^a-z]* APES,FLU, BANANA
() Группа символов (a*b)* aaabaab, abaaab, bab
| Оператор ИЛИ внутри группы символов b(a|i|e)d bad, bid, bed
\ Знак пропуска \.\|\\ .|\
{m,n} Повторение указанного количества раз от m до n (включительно) a{2,3}b{2,3} aabbb, aaabbb,aabb
^ Указывает, что символ или часть выражения находится в начале строки ^a apple, asdf, a
$ Сканировать до конца строки [A-Z]*[a-z]*$ ABCabc, zzzyx, Bob

 

О том, как применять регулярные выражения в Python для решения реальных Data Science задач, вы узнаете на нашем специализированном курсе «PNLP: NLP – обработка естественного языка с Python» в лицензированном учебном центре обучения и повышения квалификации Data Scientist’ов и IT-специалистов в Москве.

Источники
  1. https://docs.python.org/3/howto/regex.html

Добавить комментарий

Поиск по сайту