这样的事情是合理的:
import re
from collections import namedtuple
Format = namedtuple('Format', 'name format_string regex')
class Parser(object):
replacements = [Format('server', '%S', r'[A-Za-z0-9]+'),
Format('user', '%U', r'[A-Za-z0-9]+'),
Format('date', '%D', r'[0-9]{4}-[0-9]{2}-[0-9]{2}'),
Format('process_id', '%P', r'[0-9]+'),
]
def __init__(self, format):
self.format = format
self.re = re.compile(self._create_regex(format))
def _create_regex(self, format):
format = re.escape(format)
for replacement in self.replacements:
format = format.replace(r'\%s' % replacement.format_string,
r'(?P<%s>%s)' % (replacement.name,
replacement.regex,
),
)
return format
def parse(self, data):
match = self.re.match(data)
if match:
return match.groupdict()
return None
用法:
a_parser = Parser("(%D)%U_%P_%S")
print a_parser.parse("(2005-04-12)Jamie_123_Server1")
b_parser = Parser("%S - %P - %D")
print b_parser.parse("Server1 - 123 - 2005-04-12")
输出:
{'date': '2005-04-12', 'process_id': '123', 'user': 'Jamie', 'server': 'Server1'}
{'date': '2005-04-12', 'process_id': '123', 'server': 'Server1'}
本质上,我在您的自定义格式语法中的%?s 和预定义的正则表达式之间创建一个映射以匹配该参数,然后用相应的正则表达式替换给定格式字符串中的%? 字符串以构建该模式的解析器。
仅当在格式字符串中分隔“类型”的字符没有出现在它的正则表达式中,或者如果没有分隔符,那么这两个并排的正则表达式不“互相干扰”。例如,使用格式字符串:
%U%P
而我在上面分配给user 和process_id 的正则表达式,无法分辨user 的结束位置和process_id 的开始位置:
User1234
是User1 和234 还是User 和1234,或任何其他组合?但是,即使是人类也无法解决这个问题!