使用Regex匹配具有两个以上参数的函数

xxe27gdn  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(117)

我想在Python中编写一个正则表达式,它匹配具有两个以上参数的函数,例如以下表达式匹配:

function(1, 2, 3)
function(1, 2, 3, 4)
function(1, function(1, 2), 3)
function(function(function(1, 2), 2), 2, 3, 4)

但下面的人不会

function(1, 2)
function(1, function(1, function(1, 2)))
function(1, function(function(1), 2))

我最好的尝试是下面的表达式,它只适用于没有嵌套函数的情况:

\w+\((?:.*,){2,}.*\)

我应该用什么表达呢?

4ioopgfo

4ioopgfo1#

为了好玩,你可以递归地sub/用占位符(* 例如连字符 *)替换最右边的函数,并且只在最后,count每个表达式中的剩余参数:

import re

MIN_ARGS = 3

#https://peps.python.org/pep-0008/#function-and-variable-names
pyfunc = r"\b[a-zA-Z_][a-zA-Z0-9_]*"

pat = fr"({pyfunc}\(.*)(?:{pyfunc})?({pyfunc}\(.+?\))(.+)"

def fn(s):
    if len(re.findall(pyfunc, s)) > 1:
        new_s = re.sub(pat, r"\1-\3", s)
        return fn(new_s)
    else:
        return s

Regex:[ demo - first iteration ]
输出量:

# `text` is the multistring holding your expressions

for exp in text.splitlines():
    if (n:=fn(exp).count(",")) > MIN_ARGS-2:
        print(f"{exp:<50}", n+1, f"{'MATCH':>10}")
    else:
        print(f"{exp:<50}", n+1, f"{'NO-MATCH':>10}")

function(1, 2, 3)                                  3      MATCH
function(1, 2, 3, 4)                               4      MATCH
function(1, function(1, 2), 3)                     3      MATCH
function(function(function(1, 2), 2), 2, 3, 4)     4      MATCH
function(1, 2)                                     2   NO-MATCH
function(1, function(1, function(1, 2)))           2   NO-MATCH
function(1, function(function(1), 2))              2   NO-MATCH

来自 * 评论 *:
我有一个Pandas的框架,里面有一堆这样的表情。我想删除具有两个以上参数的函数调用的行
然后,您可以使用 boolean indexing,其逻辑与上面使用的相同:

import pandas as pd

df = pd.DataFrame(text.splitlines(), columns=["col"])

# is there at most two arguments ?
mask = [fn(exp).count(",") <= MIN_ARGS-2 for exp in df["col"]]

out = df.loc[mask]

输出量:

print(out)

                                        col
4                            function(1, 2)
5  function(1, function(1, function(1, 2)))
6     function(1, function(function(1), 2))
jmo0nnb3

jmo0nnb32#

使用Pypi正则表达式的递归方法:

  • “一个参数”的定义(由(?2)引用):

一个既不包含逗号也不包含括号的字符串,或者一个函数调用。
(可能的问题:如果参数看起来像a * (b + c)呢?=>目前尚未考虑)

  • 表达方式:([^(),]+|(?3))
  • 然后展开为:([^(),]+|(\b\w+\s*\((?:([^(),]+|(?3))(?:\s*,\s*(?2))*)*\)))
  • “参数”的定义:

逗号分隔的0个或多个参数的列表,即(?2)
逗号前/后可以有0个或多个空格

  • 表达方式:(?:(?2)(?:\s*,\s*(?2))*)*
  • “函数调用”的定义(由(?3)引用):

函数名+ 0或多个空格+ '(' +参数+ ')'

  • 表达方式:(\b\w+\s*\((?:([^(),]+|(?3))(?:\s*,\s*(?2))*)*\))

然后,所需的模式,具有3个或更多参数的函数,可以表示为:
(\b\w+\s*\(([^(),]+|(\b\w+\s*\((?:([^(),]+|(?3))(?:\s*,\s*(?2))*)*\)))(?:\s*,\s*(?2)){2,}\))
代码:

import regex

str = '''
function(1, 2, 3)
function(1, 2, 3, 4)
function(1, function(1, 2), 3)
function(function(function(1, 2), 2), 2, 3, 4)
function(1, 2)
function(1, function(1, function(1, 2)))
function(1, function(function(1), 2))
'''

pat = r'(\b\w+\s*\(([^(),]+|(\b\w+\s*\((?:([^(),]+|(?3))(?:\s*,\s*(?2))*)*\)))(?:\s*,\s*(?2)){2,}\))'

m = regex.findall(pat, str)
if m:
    print([x[0] for x in m])    # pick 1st element of tuples

输出量:

['function(1, 2, 3)', 'function(1, 2, 3, 4)', 'function(1, function(1, 2), 3)', 'function(function(function(1, 2), 2), 2, 3, 4)']

相关问题