Метод find
ищет подстроку в строке.
s='абракадабра'
s.find('бра')
Если подстрока не найдена, он возвращает -1
.
s.find('бро')
Можно задать дополнительный параметр - начиная с какого места искать.
s.find('бра',3)
Метод replace
возвращает копию строки, в кторой старая подстрока заменена на новую.
s.replace('бра','БРА')
Если задать дополнительный целый параметр n
, то будут заменены только первые n
вхождений старой подстроки.
s.replace('бра','БРА',1)
Но эти методы работают только с фиксированными подстроками. Для более гибкой обработки текстов можно использовать модуль re
, который позволяет искать и заменять подстроки, соответствующий некоторым образцам - регулярным выражениям.
from re import search,sub,compile
Функция search(r,s)
ищет подстроку, соответствующую регулярному выражению r
, в строке s
. Она возвращает объект сопоставления или None
, если такая подстрока не найдена. Из объекта сопоставления можно добыть полезную информацию о том, как регулярное выражение сопоставлено подстроке.
s='xy xay xaby xby'
m=search('x.y',s)
if m:
print(m.start(),m.end(),m.group())
else:
print('Не найдено')
Самая часто используемая функция того модуля - это sub
. Она возвращает копию исходной строки, в которой все подстроки, соответствующие образцу, заменены на заданную строку - замену.
sub('x.y','XXX',s)
Если мы хотим заменить только первые n
подстрок, соответствующих образцу, добавляем параметр n
.
sub('x.y','XXX',s,1)
Если мы хотим использовать одно и то же регулярное выражение несколько раз, можно скомпилировать его в некий объект, и вместо функций модуля re
вызывать методы этого объекта. Это повысит эффективность.
xy=compile('x.y')
m=xy.search(s)
print(m.group())
xy.sub('XXX',s)
В регулярном выражении все символы, кроме специальных, обозначают сами себя. Специальные символы - это .
, ^
, $
, *
, +
, ?
, \
, |
, {
, }
, [
, ]
, (
, )
. Если требуется включить в регулярное выражение один из этих символов буквально, как обычный, перед ним нужно поставить \
. Вообще, в регулярных выражениях часто приходится использовать \
. А чтобы включить этот символ в строку на питоне, его надо писать как \\
. Например, регулярное выражение, которое сопоставляется с символом \
- это \\
; в виде питонской строки его приходится писать как '\\\\'
. Неудобно. Поэтому для записи регулярных выражений часто используют сырые строки (raw, в смысле неприготовленные - не варёные и не жареные). Они пишутся как r'строка'
или r"строка"
, в них \
является вполне обычным символом. Так что это же регулярное выражение можно записать в виде сырой строки r'\\'
.
r'\n'
Специальный символ .
в регулярном выражении сопоставляется с любым (одним!) символом в строке (кроме символа '\n'
). Мы это уже видели. Конструкция [abc]
сопоставляется с a
, b
или c
. В ней можно использовать диапазоны: [0-9]
- это любая цифра, а [a-zA-Z]
- любая латинская буква. Но тут надо быть осторожным: это диапазоны в юникоднм порядке. Латинские буквы в нём действительно идут подряд, так что для обычных латинских букв (без каких-нибудь умляютов) это правильно. Но вот [а-яА-Я]
не включает все расские буквы - ё
и Ё
находятся вне этих диапазонов. Большинство специальных символов теряют свою специальность между [
и ]
и рассматриваются как обычные. Если первым символом после [
идёт ^
, то это значит любой символ, кроме тех, что дальше перечислены.
Юникод умеет много гитик, поэтому надёжнее использовать заранее определённые классы символов. Так, \d
означает любую цифру (в юникоде, в добавок к [0-9]
, их есть ещё много); \w
означает любой символ, который может присутствовать в слове - букву, цифру или _
; \s
означает любой "пробел" (пустое пространство, включая табуляцию, '\n'
и т.д.). Заглавные буквы означают дополнения к этим множествам: \D
- любая не-цифра; \W
- не встречается в словах (т.е. не буква, не цифра и не _
); \S
- любой не-пробел.
После подвыражения в регулярном выражении можно поставить *
, это означает любое число повторений (от 0 до $\infty$) этого подвыражения. Например, .*
сопоставляется с абсолютно чем угодно. Если поставить +
, то это любое ненулевое число повторений (от 1 до $\infty$). А если поставить ?
, то это 0 или 1 вхождение, т.е. это предыдущее подвыражение может присутствовать либо отсутствовать. Можно задать возможные числа повторений более явно: а{5}
означает 5 букв а
, а{2,4}
- от 2 до 4 букв а
, а{6,}
- от 6 до $\infty$ букв а
. Но это используется редко.
m=search(r'\d+','abc123xyz')
print(m.group())
^
означает начало строки, а $
- конец.
for s in ['0ab','a0b']:
if search(r'^0',s):
print('нашли')
else:
print('не нашли')
x|y
означает x
или y
. Подвыражения можно заключать в скобки.
m=search(r'(a\d+b)|(c\d+d)','xxxc123dyyy')
print(m.group())
m=search(r'0(ab)*1','x0ababab1y')
print(m.group())
Но главная польза от скобок не в этом. Каждая скобка создаёт группу. При поиске регулярного выражения в строке куски строки, сопоставленные каждому подвыражению в скобках, запоминаются, и их можно извлечь и использовать. Метод group
объекта сопоставления, вызванный без параметров, возвращает подстроку, сопоставленную всему регулярному выражению в целом; если же его вызвать с целым параметром n
, то он возвращает n
-ую группу.
m=search(r'(^[a-z]*)(\d*)([a-z]*$)','abc123xyz')
print(f'1: {m.group(1)}, 2: {m.group(2)}, 3: {m.group(3)}')
Ещё более это полезно в вызовах sub
. Почти всегда строка-замена должна содержать в себе части исходной строки, найденные при сопоставлении с регулярным выражением. Для этого в строке-замене можно использовать обозначения \1
, \2
и т.д. - они означают 1-ю, 2-ю и т.д. группы.
sub(r'(^[a-z]*)(\d*)([a-z]*$)',r'[\1][\2][\3]','abc123xyz')