2013-02-28 65 views
0

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

例如:

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(),但是,它会背叛我的初衷,所以我不喜欢这个主意。)

希望这会有所帮助。

+0

告诉我们你试过的东西。除了这个事实,它使答复者认为你正在努力工作,而不仅仅是寻找解决方案,它还让我们告诉你你错了什么,找到符合你理解的答案等。 – abarnert 2013-02-28 18:32:15

+0

在你的问题,你已经有'199'或'199,200'或'300,20,500'全部标记为一段代码。这是实际的源字符串,还是“199,200”?如果是后者...你为什么要匹配任何东西?如果你只是想匹配整个事情,你不需要正则表达式... – abarnert 2013-02-28 18:41:34

+0

你的问题仍然是模糊的。你想在第二个例子中使用字符串“(199,200)”吗?如果是这样,只是'({}).format(s)'有什么问题?那么你在谈论的其他规则是什么,它们不能像这些一样被分割(',')? – abarnert 2013-02-28 18:46:10

回答

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'] 

然而,由于萨赫勒格罗弗指出,如果这些是你输入的字符串,这相当于只调用s.split(',')。如果您的输入字符串可能有非数字,那么这将确保您只匹配数字字符串,但即使这样可能会更简单,因为filter(str.isdigit, s.split(','))

如果你想inttuple A S代替strlist 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),而你当然可以做到这一点只是对tuple调用repr,还有一个更简单的方法来获取:

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

你原来的正则表达式:

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

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

3

为什么不直接使用string.split?

numbers = targetstr.split(',') 
+0

这有什么用?这会给你“199”或“199”,“200”或“300”,“20”和“500”。 – abarnert 2013-02-28 18:39:22

+0

我想尽可能通用,因为我的另一个规则是使用不同的正则表达式,不能按照您的建议分割。如果我为这种情况使用split,我必须添加一个我不太喜欢的if-else语句。 – lhe 2013-02-28 18:41:16

+1

@lightmanhk:向我们展示实际的输入字符串,就像它们在代码中出现的一样,并有足够的多样性向我们展示所有情况以及期望的输出。否则,我们必须读懂你的想法,弄清楚你想要什么。 – abarnert 2013-02-28 18:42:16