提问人:cabralpinto 提问时间:9/11/2023 最后编辑:cabralpinto 更新时间:9/12/2023 访问量:118
使用正则表达式匹配具有两个以上参数的函数
Match functions with more than two arguments with Regex
问:
我想在 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,}.*\)
我应该用什么表达方式来代替?
答:
0赞
Timeless
9/11/2023
#1
为了好玩,您可以递归地用
占位符(例如连字符)替换最右边的函数,并且只有在最后,计算
每个表达式中的剩余参数:
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
正则表达式:[demo - 第一次迭代]
输出:
# `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 数据帧,里面有一堆这样的表达式。我会 喜欢删除具有两个以上函数调用的行 参数
然后,您可以使用与上面相同的逻辑使用布尔索引:
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))
0赞
tshiono
9/12/2023
#2
使用带有正则表达式的递归的方法:Pypi
“一个参数”的定义(引用者):
既不包含逗号也不包含括号的字符串, 或函数调用。
(可能的问题:如果参数看起来像? =>目前不考虑)(?2)
a * (b + c)
- 表达者:
([^(),]+|(?3))
- 然后扩展为:
([^(),]+|(\b\w+\s*\((?:([^(),]+|(?3))(?:\s*,\s*(?2))*)*\)))
- 表达者:
“参数”的定义:
以逗号分隔的 0 个或多个参数列表,
即逗号可以在 0 个或多个空格之前/后面(?2)
- 表达者:
(?:(?2)(?:\s*,\s*(?2))*)*
- 表达者:
“函数调用”的定义(引用者):
函数名称 + 0 个或多个空格 + '(' + 参数 + ')'(?3)
- 表达者:
(\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)']
评论
function(1, 2)
function(1, function(1, function(1, 2)))