使用DOTALL进行正则表达式,如何让它在某些时候停止?

时间:2016-12-23 15:40:18

标签: python regex

我有一个像这样的python正则表达式:

re.compile(r'(\[chartsjs\].*\[/chartsjs\])', re.DOTALL)

我正在尝试对这样的模式进行re.findall

[charts]
name: mychart
type: line
labels: fish, cat, dog
data: 4, 5, 6
data2:5, 7, 9
[/charts]

this is some text

[charts]
name: second
type: line
labels: 100, 500, 1000
data: 50, 100, 10000
data2: 100, 100, 100
[/charts]

但似乎它匹配第一个[charts]到最后一个[charts]并抓住中间的所有内容,因为当我将它打印到控制台时我看到了这个:

[u'[chartsjs]\r\nname: mychart\r\ntype: line\r\nlabels: fish, cat, dog\r\ndata: 4, 5, 6\r\ndata2:5, 7, 9\r\n[/chartsjs]\r\n\r\nthis is some text now fool\r\n\r\n[chartsjs]\r\nname: second\r\ntype: line\r\nlabels: 100, 500, 1000\r\ndata: 50, 100, 10000\r\ndata2: 100, 100, 100\r\n[/chartsjs]']

我希望正则表达式返回第一个匹配,消除任意测试,然后找到另一个任意数量的匹配。有没有办法做到这一点?

2 个答案:

答案 0 :(得分:5)

你的正则表达式只有一个问题。

.*会贪婪地匹配其路径中的所有内容。当遇到第一个结束[/charts]时,它将进一步检查是否还有更多[/charts]。如果找到,那么它将继续。

要让它在第一个[/charts]停止,我们需要通过添加问号使其变得懒惰。 .*?这将保持匹配所有内容并在第一个[/charts]

停止

看看我测试过它:

import re

a="""
[charts]
name: mychart
type: line
labels: fish, cat, dog
data: 4, 5, 6
data2:5, 7, 9
[/charts]

this is some text

[charts]
name: second
type: line
labels: 100, 500, 1000
data: 50, 100, 10000
data2: 100, 100, 100
[/charts]
"""

for c in re.findall('(\[charts\].*?\[/charts\])',a, re.DOTALL):
    print c

输出:

[charts]
name: mychart
type: line
labels: fish, cat, dog
data: 4, 5, 6
data2:5, 7, 9
[/charts]
[charts]
name: second
type: line
labels: 100, 500, 1000
data: 50, 100, 10000
data2: 100, 100, 100
[/charts]

答案 1 :(得分:1)

这里最重要的是你希望。*成为。*?。还有其他方法来优化正则表达式,正如其他人已经回答的那样,但我认为你的问题的根源是你想要匹配所有你看到的那些[/ charts]模式,哪个?会给你。