Python 正则表达式:多行和非贪婪模式

3 投票
5 回答
2634 浏览
提问于 2025-04-18 01:08

我有一些这样的文本:

cc.Action = {
};

cc.FiniteTimeAction = {

};

cc.Speed = {

};

我想要的结果(列表)是:

['cc.Action = {}', 'cc.FiniteTimeAction = {}', 'cc.Speed = {}']

这是我尝试过的:

input = codecs.open(self.input_file, "r", "utf-8")
content = input.read()
result = re.findall('cc\..*= {.*};', content, re.S)
for r in result:
    print r
    print '---------------'

结果是:

[
'cc.Action = {
};

cc.FiniteTimeAction = {

};

cc.Speed = {

};'
]

任何建议都非常感谢,谢谢 :)

5 个回答

0
>>> 'cc.Action = {\n};\n\ncc.FiniteTimeAction = {\n\n};\n\ncc.Speed = {\n\n};'.replace('\n','').split(";")
['cc.Action = {}', 'cc.FiniteTimeAction = {}', 'cc.Speed = {}', '']

这个方法对你有效。

0

如果你根据 ; 来进行分割:

codes.split(';')

输出结果:

['cc.Action = {}', ' cc.FiniteTimeAction = {}', 'cc.Speed = {}', '']
0

问题在于,你使用了贪婪匹配。你需要使用非贪婪匹配,也就是用 ? 操作符。

import re
print [i.replace("\n", "") for i in re.findall(r"cc\..*?{.*?}", data, re.DOTALL)]
# ['cc.Action = {}', 'cc.FiniteTimeAction = {}', 'cc.Speed = {}']

如果你不使用 .*?,那么 .*{ 会匹配到字符串中的最后一个 {。这样的话,所有的字符串就会被当作一个整体来处理。当你使用非贪婪匹配时,它只会匹配到当前字符后第一个出现的 {

另外,这个问题也可以不使用正则表达式来解决,像这样:

print [item.replace("\n", "") for item in data.split(";") if item]
# ['cc.Action = {}', 'cc.FiniteTimeAction = {}', 'cc.Speed = {}']

只需根据 ; 来分割字符串,如果当前的字符串不为空,就把所有的 \n(换行符)替换成空字符串。

0

正如你标题所说,问题出在“贪婪”上:cc\..*= 会从字符串的开头匹配到最后一个 =

你可以通过使用“懒惰量词”来避免这种情况,它会尽量在下一个字符出现的最早位置停止匹配:

cc\..*?= {.*?};

这里有个演示:http://regex101.com/r/oL4yG7

1

这个匹配的开始部分看起来是 cc.,而结束部分是 ;,所以我们可以使用这个模式:

'cc\.[^;]+'

这意味着,我们先匹配 cc.,然后匹配每一个不是 ; 的字符([] 是用来表示字符类的,^ 是用来取反的)。

你也可以使用非贪婪重复 *?,但在这种情况下,我觉得这样做有点过于复杂。正则表达式越简单越好。

为了得到想要的输入,你还需要去掉换行符。综合起来,我建议使用:

result = re.findall('cc\.[^;]*;', content.replace('\n', ''))

撰写回答