0

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

例如:

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

希望这会有所帮助。

4

2 回答 2

3

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

numbers = targetstr.split(',')
于 2013-02-28T18:36:20.397 回答
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(',')).

如果你想要 a tupleof ints 而不是 a listof strs:

>>> 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)

如果你想要 string (300, 20, 500),虽然你当然可以通过调用repr来做到这一点tuple,但有一种更简单的方法来获得它:

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

你原来的正则表达式:

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

... 将准确返回两个组,因为模式中有两个组。而且,由于你明确地将它包装在^and$中,它必须匹配整个字符串,所以findall在这里不会帮助你——它会找到与match.

于 2013-02-28T18:35:35.410 回答