Соответствует целому числу. Возможно, со знаком.
r"\([+-]?\d+\)"
Число, стоящее в скобках. Скобки используются в самих регулярных выражениях, поэтому они экранируются "\"
.
r"[a–cA–C]{2}"
Соответствует строке из двух букв « a
», « b
» или « c
». Например, « Ac
», « CC
», « bc
».
r"aa|bb|cc|AA|BB|CC"
Строка из двух одинаковых букв.
r"([a–cA–C])\1"
Строка из двух одинаковых букв, но шаблон задан с использованием групп
r"aa|bb"
Соответствует « aa
» или « bb
»
r"a(a|b)b"
Соответствует « aab
» или « abb
»
r"^(?:\d{8}|\d{4}):\s*(.*)$"
Соответствует строке, которая начинается с набора из восьми или четырех цифр и двоеточия. Все, что идет после двоеточия и после следующих за ним пробелов, выделяется в группу с номером 1, тогда как набор цифр в группу не выделен.
r"(\w+)=.*\b\1\b"
Слова слева и справа от знака равенства присутствуют. Операнд "\1"
соответствует группе с номером 1, выделенной с помощью скобок.
r"(?P\w+)=.*\b(?P=var)\b"
То же самое, но теперь используется именованная группа var
.
r"\bregular(?=\s+expression)"
Соответствует слову « regular
» только в том случае, если за ним после пробелов следует « expression
»
r"(?<=regular )expression"
Соответствует слову « expression
», перед которым стоит « regular
»и один пробел.
Следует заметить, что примеры со взглядом назад могут сильно влиять на производительность, поэтому их не стоит использовать без особой необходимости.
Отладка регулярных выражений
Следующий небольшой сценарий позволяет отлаживать регулярное выражение, при условии, что есть пример строки, которой шаблон должен удовлетворять. Взят кусочек лога iptables, его необходимо разобрать для получения полей. Интересны строки, в которых после kernel:
стоит PAY:
, а в этих строках нужно получить дату, значения DST, LEN и DPT:
import re
def debug_regex(regex, example):
"""Отладка рег. выражения. Перед отладкой лучше убрать лишние скобки """
last_good = ""
for i in range(1, len(regex)):
try:
if re.compile(regex[:i]).match(example):
last_good = regex[:i]
except:
continue
return last_good
example = ""«Nov 27 15:57:59 lap kernel: PAY: IN=eth0 OUT=
MAC=00:50:da:d9:df:a2:00:00:1c:b0:c9:db:08:00 SRC=192.168.1.200
DST=192.168.1.115
LEN=1500 TOS=0x00 PREC=0x00 TTL=64 ID=31324 DF PROTO=TCP SPT=8080 DPT=1039
WINDOW=17520 RES=0x00 ACK PSH URGP=0»""
log_re = r"""[A–Za–z]{3}\s+\d+\s+\d\d\d\d:\d\d) \S+ kernel: PAY: .+
DST=(?P\S+).* LEN=(?P\d+).* DPT=(?P\d+) """
print debug_regex(log_re, example)
Функция debug_regex()
пробует сопоставлять пример с увеличивающимися порциями регулярного выражения и возвращает последнее удавшееся сопоставление:
[A–Za–z]{3}\s+\d+\s+\d\d
Сразу видно, что не поставлен символ :
.
Примеры применения регулярного выражения
Предыдущий пример регулярного выражения позволит выделить из лога записи с определенной меткой и подать их в сокращенном виде:
import re
log_re = re.compile(r"""(?P[A–Za–z]{3}\s+\d+\s+\d\d:\d\d:\d\d) \S+
kernel:
PAY: .+ DST=(?P\S+).* LEN=(?P\d+).* DPT=(?P\d+) """)
for line in open("message.log"):
m = log_re.match(line)
if m:
print "%(date)s %(dst)s:%(dpt)s size=%(len)s" % m.groupdict()
В результате получается
Nov 27 15:57:59 192.168.1.115:1039 size=1500
Nov 27 15:57:59 192.168.1.200:8080 size=40
Nov 27 15:57:59 192.168.1.115:1039 size=515
Nov 27 15:57:59 192.168.1.200:8080 size=40
Nov 27 15:57:59 192.168.1.115:1039 size=40
Nov 27 15:57:59 192.168.1.200:8080 size=40
Nov 27 15:57:59 192.168.1.115:1039 size=40
Хороший пример регулярного выражения можно найти в модуле fpformat
. Это регулярное выражение позволяет разобрать запись числа (в том виде, в каком числовой литерал принято записывать в Python):
decoder = re.compile(r'^([-+]?)0*(\d*)((?:\.\d*)?)(([eE][-+]?\d+)?)$')
# Следующие части числового литерала выделяются с помощью групп:
# \0 — весь литерал
# \1 — начальный знак или пусто
# \2 — цифры слева от точки
# \3 — дробная часть (пустая или начинается с точки)
# \4 — показатель (пустой или начинается с 'e' или 'E')
Например:
import re
decoder = re.compile(r'^([-+]?)0*(\d*)((?:\.\d*)?)((?:[eE][-+]?\d+)?)$')
print decoder.match("12.234").groups()
print decoder.match(" — 0.23e–7").groups()
print decoder.match("1e10").groups()
Получим
('', '12', '.234', '')
('-', '', '.23', 'e–7')
('', '1', '', 'e10')
В некоторых приложениях требуется производить в тексте сразу несколько замен. Для решения этой задачи можно использовать метод sub()
вместе со специальной функцией, которая и будет управлять заменами:
Читать дальше
Конец ознакомительного отрывка
Купить книгу