python重新匹配组

时间:2013-02-28 18:30:39

标签: python regex

我想从字符串中提取一些字段,但我不确定它们有多少。 我使用了正则表达式,但有些问题我不明白。

例如:

  199  -> (199)
  199,200  -> (199,200)
  300,20,500 -> (300,20, 500)

我尝试过,但有些我无法让它发挥作用。 希望有人能给我一些建议。我会很感激。

我试过的正则表达式:

>>> re.match('^(\d+,)*(\d+)$', '20,59,199,300').groups()
('199,', '300')
// in this, I do not really care about ',' since I could use .strip(',') to trim that. 

我做了一些谷歌:并试图使用re.findall,但我不知道如何得到这个:

>>> re.findall('^(\d+,)*(\d+)$', '20,59,199,300')
[('199,', '300')]

----------------------------------------------- -------更新

我没有讲完整个故事就意识到这个问题可能令人困惑。 基本上我想验证在crontab(或类似)

中定义的语法

我为_VALID_EXPRESSION创建了一个数组:它是一个嵌套的元组。

 (field_1,
  field_2,
 )

对于每个field_1,它有两个元组,

 field_1:   ((0,59),        (r'....', r'....'))
            valid_value   valid_format 

在我的代码中,它看起来像这样:

_VALID_EXPRESSION =  \
 12     (((0, 59), (r'^\*$', r'^\*/(\d+)$', r'^(\d+)-(\d+)$',
 13                 r'^(\d+)-(\d+)/(\d+)$', r'^(\d+,)*(\d+)$')),   # second
 14      ((0, 59), (r'^\*$', r'^\*\/(\d+)$', r'^(\d+)-(\d+)$',
 15                 r'^(\d+)-(\d+)/(\d+)$', r'^(\d+,)*(\d+)$')),   # minute
 16        .... )

在我的解析函数中,我所要做的就是提取所有组并查看它们是否在有效值范围内。

我需要的一个正则表达式是它能够正确匹配此字符串'50,200,300'并在这种情况下提取所有数字。 (我当然可以使用split(),然而,它会背叛我的初衷。所以,我不喜欢这个主意。)

希望这会有所帮助。

2 个答案:

答案 0 :(得分:3)

为什么不使用string.split?

numbers = targetstr.split(',')

答案 1 :(得分:1)

使用正则表达式的最简单的解决方案是:

r"(\d+,?)"

您可以使用findall获取所需的300,20,500。或者,如果您不想要逗号:

r"(\d+),?"

这匹配一组1个或更多数字,后跟0或1个逗号(不在组中)。

无论哪种方式:

>>> s = '300,20,500'
>>> r = re.compile(r"(\d+),?")
>>> r.findall(s)
['300', '20', '500']

然而,正如Sahil Grover指出的那样,如果这些是你的输入字符串,这相当于只调用s.split(',')。如果您的输入字符串可能包含非数字,那么这将确保您只匹配数字字符串,但即使这样也可能更简单,因为filter(str.isdigit, s.split(','))

如果您需要tuple int而不是list str s:

>>> tuple(map(int, r.findall(s)))
(300, 20, 500)

如果您发现理解/生成器表达式比map / filter调用更容易阅读:

>>> tuple(int(x) for x in r.findall(s))
(300, 20, 500)

或者更简单:

>>> tuple(int(x) for x in s.split(',') if x.isdigit())
(300, 20, 500)

如果你想要字符串(300, 20, 500),当然你可以通过调用repr上的tuple来做到这一点,那么有一种更容易实现的方法:

>>> '(' + s + ')'
'(300, 20, 500)'

你原来的正则表达式:

'^(\d+,)*(\d+)$'

...将准确返回两个组,因为模式中只有两个组。而且,由于您明确将其包含在^$中,因此必须匹配整个字符串,因此findall不会帮助您 - 它会找到完全相同的一个匹配(两个组)为match