Python正则表达式命名组(0或1匹配)

时间:2014-11-17 17:21:50

标签: python regex

我正在尝试解析以下行Python:

s='SIP/200259 (In use) has taken 6 calls (last was 8932 secs ago) (order: 0)'

因此我制作了我的正则表达式:

sip_patt = re.compile(r'''SIP/(?P<ext>\d+).* # Extension
                          (?P<inuse>In\suse).* # Speaking
                          has\staken\s(?P<taken>\d+|no).* # Taken
                          last\swas\s(?P<last>\d+).* # Last Seen
                          order:\s(?P<order>\d+).* # Order in the queue''', re.X)

这产生了期望的结果:

sip_patt.match(s).groups()
('200259', 'In use', '6', '8932', '0')

然而,有时初始字符串可能如下所示(注意“括号内未使用”):

s='SIP/200259 (Not in use) has taken 6 calls (last was 8932 secs ago) (order: 0)'

因此,为了避免所有“ifs”和“elses”,我想稍微改变我的捕获逻辑以匹配我的命名组“inuse”的0或1个实例,但是这根本不起作用。通过增加 ”?”或者我的命名组旁边的{0,1}我总是得不到匹配:

s='SIP/200259 (In use) has taken 6 calls (last was 8932 secs ago) (order: 0)'
sip_patt = re.compile(r'''SIP/(?P<ext>\d+).* # Extension
                          (?P<inuse>In\suse)?.* # Speaking
                          has\staken\s(?P<taken>\d+|no).* # Taken
                          last\swas\s(?P<last>\d+).* # Last Seen
                          order:\s(?P<order>\d+).* # Order in the queue''', re.X)
sip_patt.match(s).groups()
('200259', None, '6', '8932', '0')

我错过了什么?

1 个答案:

答案 0 :(得分:1)

你缺少什么?

.*是非常危险的metasequance。它很贪婪,并试图匹配尽可能多的字符。

那是你写的时候

SIP/(?P<ext>\d+).* .*将匹配包括(In use)在内的任何内容。由于(?P<inuse>In\suse)?是可选字段,因此正则表达式计算机在之前的.*

中包含此字段

如何纠正

您可以限制SIP digits后面的内容。例如,显然In use(开头,而不是匹配.*我们会尝试的任何内容[^(]除了(以外的其他任何内容。这样可确保仅匹配(In use(?P<inuse>In\suse)?安全匹配

示例:

>>> sip_patt = re.compile(r'''SIP/(?P<ext>\d+)[^(]* # Extension
...                           \((?P<inuse>In\suse)?\).* # Speaking
...                           has\staken\s(?P<taken>\d+|no).* # Taken
...                           last\swas\s(?P<last>\d+).* # Last Seen
...                           order:\s(?P<order>\d+).* # Order in the queue''', re.X)
>>> sip_patt.match(s).groups()
('200259', 'In use', '6', '8932', '0')

注意我在?P<inuse>In\suse)?内限制了\( \),以便与安全性相关匹配