解析嵌套函数以提取python中的每个内部函数

解析嵌套函数以提取python中的每个内部函数,python,Python,我有一个嵌套表达式,如下所示 expression = 'position(\'a\' IN Concat("function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" , "function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" ))' 我希望通过首先检索嵌套函数,然后检索外部函

我有一个嵌套表达式,如下所示

 expression = 'position(\'a\' IN Concat("function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" ,  "function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" ))'
我希望通过首先检索嵌套函数,然后检索外部函数来获得输出

['Concat("function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" ,  "function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" )','position(\'a\' IN Concat("function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" ,  "function_test"."PRODUCT_CATEGORIES"."CATEGORY_NAME" ))']
下面是我尝试过的代码

 result = []
 for i in range(len(expression)):
     if expression[i]=="(":
        a.append(i)
     elif expression[i]==")":
          fromIdx=a.pop()
          fromIdx2=max(a[-1],expression.rfind(",", 0, fromIdx))
          flag=False
          for (fromIndex, toIndex) in first_Index:
             if fromIdx2 + 1 >= fromIndex and i <= toIndex:
                 flag=True
                 break
          if flag==False:
             result.append(expression[fromIdx2+1:i+1])
我的代码中这个表达式的结果将是正确的。 在第一个表达式中,我提到,操作符中有,而不是,“因此我的代码不起作用


请帮助

如果您希望它可靠,您需要一个成熟的SQL解析器。幸运的是,有一个现成的解决方案:。一旦您有了一个已解析的令牌树,您就可以遍历它并执行您需要的操作:

import sqlparse

def extract_functions(tree):
    res = []
    def visit(token):
        if token.is_group:
            for child in token.tokens:
                visit(child)
        if isinstance(token, sqlparse.sql.Function):
            res.append(token.value)
    visit(tree)
    return res

extract_functions(sqlparse.parse(expression)[0])
解释。
sqlparse.parse(expression)
解析字符串并返回语句的元组。由于示例中只有一条语句,我们可以只使用第一个元素。如果有许多语句,则应该迭代所有元组元素


extract_functions
首先使用
token.is_group
递归遍历已解析的令牌树深度(因为您希望内部调用出现在外部调用之前)。要确定当前令牌是否为叶,测试当前令牌是否为函数,如果是,则附加其字符串表示形式(
token.value
)到结果列表。

请格式化。@leoOrion现在已正确格式化。请检查谢谢您的回答。它是否适用于任何类型的复杂表达式,并从最内层返回嵌套函数。使用sqlparse包可行吗?使用sqlparse有什么缺点吗?除非解析器中有bug,否则它应该可以工作。我不知道有什么缺点。可能是,如果您对使用第三方软件包有一些非常特殊的限制,这可能会造成麻烦。但在一般情况下,它应该是完美的。这是Python中最酷的东西之一,你可以找到一个开箱即用的软件包,几乎可以解决所有问题。好的,谢谢。你能给我解释一下这段代码吗。添加了一个解释。最近在这段代码中发现一个问题,说它不支持函数名后面的空格示例
upper(name)
不起作用。你能帮我一下吗
import sqlparse

def extract_functions(tree):
    res = []
    def visit(token):
        if token.is_group:
            for child in token.tokens:
                visit(child)
        if isinstance(token, sqlparse.sql.Function):
            res.append(token.value)
    visit(tree)
    return res

extract_functions(sqlparse.parse(expression)[0])