【问题标题】:Over-matching with regular expression function re.findall() in Python与 Python 中的正则表达式函数 re.findall() 过度匹配
【发布时间】:2018-04-22 03:58:35
【问题描述】:

我正在使用 Python 2,我有一个字符串如下。

s = """
f = function(x) sum(is.na(x))

apply(xdat, 2, f)

sum_it = function(xdat) {
    ans = apply(xdat, 2, sum)
    return(ans)
}
"""

我打算提取由{} 包围的sum_it 函数。我使用了下面的代码

print(re.findall(r"\s+[\w._]+ = function\(.+?\)\s*{.+?\n}\s", s, flags=re.DOTALL)[0])

这给了我错误的结果:

f = function(x) sum(is.na(x))

apply(xdat, 2, f)

sumit = function(xdat) {
    ans = apply(xdat, 2, sum)
    return(ans)
}

我明确表示我想要的子字符串应该在其中包含{}。但是为什么这个正则表达式不能排除字符串中明显没有{} 的开头部分呢?我怎样才能得到这个:

sumit = function(xdat) {
    ans = apply(xdat, 2, sum)
    return(ans)
}

【问题讨论】:

    标签: python regex findall


    【解决方案1】:

    这是括号中的通配符匹配。由于您使用的是“。”为了匹配参数列表,它也可以匹配括号字符。第一场比赛包括第一个开放括号和最后一个封闭括号之间的所有内容。如果你把这行改成这样,它应该可以工作(虽然你在开始时会得到很多额外的空间,并且有更好的方法来做这个匹配):

    print(re.findall(r"\s+[\w._]+ = function\([^)]*\)\s*{.+?\n}\s", s, flags=re.DOTALL)[0])
    

    讨论后更新:

    乍一看,非贪婪限定符似乎会寻找字符最少的匹配子字符串。但是,它真正起作用的方式是,它寻找可以匹配的 first 子字符串,然后在其中匹配尽可能少的字符。

    【讨论】:

    • 谢谢!它确实解决了我的问题。但是我添加了非贪婪限定符function\(.+?\),为什么? 对我不起作用?
    • 嗯,你是对的。我误读了,现在我不确定为什么非贪婪限定符不起作用。我得再看看这个
    • 好的,我知道为什么。这有点令人困惑:贪婪适用于匹配开始后消耗多少个字符,但它检查一个消耗最少字符的所有潜在匹配。因此,即使它不是贪婪的,它仍然会采用它找到的 first 匹配项。
    猜你喜欢
    • 2012-02-18
    • 2021-09-30
    • 2023-03-25
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 1970-01-01
    • 2015-07-02
    • 2016-07-01
    相关资源
    最近更新 更多