python re 匹配组
我想从字符串中提取一些字段,但我不确定具体有多少个。我用了正则表达式,但遇到了一些我不理解的问题。
比如说:
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 个回答
为什么不直接用字符串的split方法呢?
numbers = targetstr.split(',')
最简单的解决方案是用正则表达式来实现:
r"(\d+,?)"
你可以用 findall
来获取你想要的 300,
、20,
和 500
。或者,如果你不想要逗号的话:
r"(\d+),?"
这个表达式可以匹配一个或多个数字,后面跟着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
(字符串):
>>> 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
一样的那个匹配(两个组)。