如何使未来的捕获取决于python正则表达式中的早期匹配?

时间:2013-04-23 17:44:21

标签: python regex

我正在尝试使用正则表达式解析以下格式的消息:

  • /log/<sender>
  • /error/<sender>
  • /state/<sender>/<variable_name>

我希望能够检索消息的类型,消息的发送者以及消息是state消息的变量名称。请注意,日志和错误消息不能在此架构下包含变量名称。

我尝试使用以下模式执行此操作:

address_pattern = re.compile(
    r'''/
       ((?P<type> log)/(?P<sender> [^/]*))
     | ((?P<type> error)/(?P<sender> [^/]*))
     | ((?P<type> state)/(?P<sender> [^/]*)/(?P<parameter> [^/]*))
    ''', re.VERBOSE)

但是,这不是一个有效的模式,因为捕获组<type><sender>被定义了多次(尽管逻辑上只有一个匹配)。

是否有单个正则表达式可以为我解析此字符串并提供三个匹配项?

2 个答案:

答案 0 :(得分:2)

怎么样:

r'/(?P<type>log|error|state)/(?P<sender>[^/]+)(?:/(?P<parameter>[^/]+))?'

如果人们尝试/error/<sender>/<variable>之类的内容,您可以检查语义并抛出错误。

正则表达式有限。根据定义,它们不允许您根据之前的匹配稍后做出决定。一些语法(例如Python的)可以让你作弊并重复使用之前的匹配。例如r'<(a|p|div)></\1>',但这就是你可以去的地方。否则,您只能使用DFA

答案 1 :(得分:0)

我找到的解决方案不是100%正则表达式,但行为相同:

对于字符串s,您有

state_pat = re.compile(r'/(?P<type>state)/(?P<sender>[^/]+)/(?P<parameter>[^/]+)')
log_pat = re.compile(r'/(?P<type>(log|warning|error))/(?P<sender>[^/]+)')
ping_pat = re.compile(r'/(?P<type>ping)/(?P<sender>[^/]+)')

match = state_pat.match(s) or log_pat.match(s) or ping_pat.match(s)

基本上,将需要重用组名的每个逻辑划分为自己的模式,然后使用or的短路来返回匹配的第一个。然后,您可以使用match.group('type')来测试匹配的模式,并且行为与原始问题中的预期一致。

同样,/log/sender/parameter等字符串也不匹配,您将被退回None