"""Отладка рег. выражения. Перед отладкой лучше убрать лишние скобки """
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
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
kernel:
PAY: .+ DST=(?P
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()
вместе со специальной функцией, которая и будет управлять заменами:
import re
def multisub(subs_dict, text):
def _multisub(match_obj):
return str(subs_dict[match_obj.group()])
multisub_re = re.compile("|".join(subs_dict.keys()))
return multisub_re.sub(_multisub, text)
repl_dict = {'one': 1, 'two': 2, 'three': 3}