python 3.3 RE如何抓住可能的组?

时间:2014-02-12 14:31:05

标签: python regex

如果组编号未知(> = 0),则RE仅捕获最后一组:

>>> re.findall(r"{% url '(\w+)'(?:\s+(\w+))* %}","{% url 'a' b %}")
[('a', 'b')]
>>> re.findall(r"{% url '(\w+)'(?:\s+(\w+))* %}","{% url 'a' b c %}")
[('a', 'c')]
>>> re.findall(r"{% url '(\w+)'(?:\s+(\w+))* %}","{% url 'a' b c e %}")
[('a', 'e')]

如何抓住所有这样的群体(我想):

>>> re.findall(r"{% url '(\w+)'(?:\s+(\w+))* %}","{% url 'a' b %}")
[('a', 'b')]
>>> re.findall(r"{% url '(\w+)'(?:\s+(\w+))* %}","{% url 'a' b c %}")
[('a', 'b', 'c')]
>>> re.findall(r"{% url '(\w+)'(?:\s+(\w+))* %}","{% url 'a' b c e %}")
[('a', 'b', 'c', 'e')]

注意,我这是一个简单的情况,很容易理解我的问题。因此,像s.split()这样的解决方案不适用于复杂的解决方案。

我真正需要的是(请注意空格数是未知的(> = 1)):

grab ["'funcname'", 'first'] from "{% url 'funcname'    first   %}"
grab ["'funcname'", 'first', 'second'] from "{% url 'funcname'  first    second %}"
grab ["'funcname'", 'first', 'second','third'] from "{% url 'funcname'  first second     third    %}"

或者更复杂:

grab ["'funcname'", 'first','fir'] from "{% url 'funcname'    first = fir   %}"
grab ["'funcname'", 'first','fir', 'second', 'sec'] from "{% url 'funcname'  first=fir    second   = sec %}"
grab ["'funcname'", 'first','fir', 'second', 'sec', 'third', 'thi'] from "{% url 'funcname'  first =fir    second = sec    third=thi    %}"

1 个答案:

答案 0 :(得分:1)

你在组中放了一个乘数:

(?:\s+(\w+))*

但是群体不会成倍增加;他们有一个固定的组号,每个匹配都分配给该组号。因此,你只能看到最后一场比赛。

您必须捕获一个组中的所有候选人并随后拆分:

[r[:1] + tuple(r[1].split()) 
 for r in re.findall(r"{% url '(\w+)'((?:\s+\w+)*) %}", inputtext)]

请注意,捕获组现在捕获所有(?:\s+\w+)*模式。

演示:

>>> import re
>>> inputtext = "{% url 'a' b c e %}"
>>> [r[:1] + tuple(r[1].split()) 
...  for r in re.findall(r"{% url '(\w+)'((?:\s+\w+)*) %}", inputtext)]
[('a', 'b', 'c', 'e')]

您的第二个表单更复杂,并且要求您使用另一个正则表达式来拆分匹配项:

from itertools import chain

[r[:1] + tuple(chain(*re.findall(r'(\w+)\s*=\s*(\w+)', r[1])))
 for r in re.findall(r"{% url '(\w+)'((?:\s+\w+\s*=\s*\w+)*) \s*%}", inputtext)]

演示:

>>> inputtext = "{% url 'funcname'  first =fir    second = sec    third=thi    %}"
>>> [r[:1] + tuple(chain(*re.findall(r'(\w+)\s*=\s*(\w+)', r[1])))
...  for r in re.findall(r"{% url '(\w+)'((?:\s+\w+\s*=\s*\w+)*) \s*%}", inputtext)]
[('funcname', 'first', 'fir', 'second', 'sec', 'third', 'thi')]