婧若钰熙 发表于 2023-11-20 00:05:53

Python 按规则解析并替换字符串中的变量及函数

按规则解析并替换字符串中的变量及函数

需求

1、按照一定规则解析字符串中的函数、变量表达式,并替换这些表达式。这些函数表达式可能包含其它函数表达式,即支持函数嵌套
2、函数表达式格式:${__函数名称()}、${__函数名称( 函数参数 )}
3、变量表达式格式:${ varName }
注意:

[*]函数名称以__打头
[*]${之间不能有空格
[*]函数名称和函数的左括号 ( 之间不能有空隔
[*]函数支持嵌套,形如:${ __function1( ${__function2()} )}
[*]函数参数如果是字符串(包括由嵌套函数返回值),需要使用单引号、双引号引用 形如 ${ __function1( "str_value",123)} ,${ __function1(key="arg_value")},${ __function1(key=\'arg_value\')},
[*]函数参数支持python原生函数 形如${ __function1( set() )}
实现代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import re

REGEX_PATTERN_FOR_DYNAMIC =re.compile('(\${\s*.+\s*})', re.DOTALL) # 用于获取动态值中的表达式

REGEX_PATTERN_FOR_VAR = re.compile('(\${\s*[^{}]+s*})', re.DOTALL) # 用于获取动态值中的变量表达式
REGEX_PATTERN_FOR_FUNC_DEFINITION = re.compile('\${\s*__.+?\(.*?\)\s*}', re.DOTALL) # 用于获取函数表达式中的函数名称及其参数
REGEX_PATTERN_FOR_FUNC_NAME_WITH_ARGS = re.compile('\${\s*(__.+?)\((.*?)\)\s*}', re.DOTALL) # 用于获取函数表达式中的函数名称及其参数


def test_func1():
    print('-----func1 called-----')

def test_func2(arg1, arg2):
    print('-----func2 called-----')
    print('arg1:', arg1, 'arg2:', arg2)
    print()
    return "func2"

def test_func3(arg1, arg2):
    print('-----func3 called-----')
    print('arg1:', arg1, 'arg2:', arg2)
    print()
    return 999

def test_func4(arg1, arg2):
    print('-----func4 called-----')
    print('arg1:', arg1, 'arg2:', arg2)
    print()
    return 9.99

def test_func5(arg1, arg2):
    print('-----func5 called-----')
    print('arg1:', arg1, 'arg2:', arg2)
    print()
    return ['e1', 'e2']

def test_func6(arg1, arg2):
    print('-----func6 called-----')
    print('arg1:', arg1, 'arg2:', arg2)
    print()
    return False

def test_func7(*args, **kwargs):
    print('-----func7 called-----')
    for i, arg in enumerate(args):
      print('arg%s = %s' % (i, arg))

    for i, kwargs in enumerate(kwargs):
      print('kwarg%s = ' % i, kwargs)


user_name = 'shouke'
addr = 'unknown'
int_var = 3



def evaluate_dynamic_value(dynamic_value):
    '''解析动态值
    @params: dynamic_value 动态值,如果是字符串类型,带双引号、单引号
    '''

    if REGEX_PATTERN_FOR_VAR.search(dynamic_value):
      pattern = REGEX_PATTERN_FOR_VAR
    elif REGEX_PATTERN_FOR_FUNC_DEFINITION.search(dynamic_value):
      pattern = REGEX_PATTERN_FOR_FUNC_DEFINITION
    else:
      return dynamic_value

    var_express_value = None

    match_res = pattern.findall(dynamic_value)
    for var_express in match_res:
      var_name = var_express.strip()
      if var_name.startswith('__'): # 函数
            function_mateched = REGEX_PATTERN_FOR_FUNC_DEFINITION.findall(var_express)
            for function in function_mateched:
                func_info_matched = REGEX_PATTERN_FOR_FUNC_NAME_WITH_ARGS.findall(var_express)
                for func_info in func_info_matched:
                  func_name, func_args = func_info
                  # print('---',func_name, func_args)
                  if REGEX_PATTERN_FOR_DYNAMIC.search(func_args):
                        func_args = evaluate_dynamic_value(func_args)
                  func_value = eval('{func_name}({func_args})'.format(func_name=func_name.lstrip('_'), func_args=func_args))
                  if func_value is None:
                        func_value = ''
                  var_express_value = var_express.replace(function, str(func_value))
      else: # 变量,不支持嵌套,直接取值
            var_express_value = globals().get(var_name, '')

      if var_express_value is not None:
            dynamic_value = dynamic_value.replace(var_express, str(var_express_value))

            if REGEX_PATTERN_FOR_DYNAMIC.search(dynamic_value): # 替换后的动态值,还是可能存在动态值
                dynamic_value = evaluate_dynamic_value(dynamic_value)

    return dynamic_value


# 测试验证
print(evaluate_dynamic_value('${ user_name }')) # 输出:shouke
print(evaluate_dynamic_value('${ addr }')) # 输出:unknown
print(evaluate_dynamic_value('username:${ user_name } addr:${ addr }')) # 输出:username:shouke addr:unknown

print(evaluate_dynamic_value('${ __test_func1() }'))
#调用输出:
#-----func1 called-----

print(evaluate_dynamic_value('${ __test_func2("user", "shouke") }')) # 输出:func2
#调用输出:
#-----func2 called-----
# arg1: user arg2: shouke
#
print(evaluate_dynamic_value('test_func1 return: ${ __test_func1() }, test_func2 return: ${ __test_func2("user", "shouke") }')) # 输出:test_func1 return: , test_func2 return: func2
# 调用输出:
#-----func1 called-----
#-----func2 called-----
#arg1: user arg2: shouke
#
print(evaluate_dynamic_value('${ __test_func7("addr", "sz") }'))
#-----func7 called-----
#调用输出:
#arg0 = addr
#arg1 = sz
print(evaluate_dynamic_value('${ __test_func7(110,'
                           ' 11.56, '
                           '"test", '
                           ', '
                           '["2", "4", "6"], '
                           '1 == 1, '
                           'True, '
                           '{"username": "shouke", "age": "unknown"},'
                           'position="sz",'
                           'hobby="pingpong",'
                           'books=["unkonwn"]) }'))
#调用输出:
# -----func7 called-----
# arg0 = 110
# arg1 = 11.56
# arg2 = test
# arg3 =
# arg4 = ['2', '4', '6']
# arg5 = True
# arg6 = True
# arg7 = {'username': 'shouke', 'age': 'unknown'}
# kwarg0 =position
# kwarg1 =hobby
# kwarg2 =books

print(evaluate_dynamic_value('${ __test_func7("${user_name}", ${int_var})}'))
#调用输出:
#-----func7 called-----
#arg0 = shouke
#arg1 = 3
print(evaluate_dynamic_value('var: ${addr} function: ${ __test_func7( ${__test_func6("${user_name}", ${int_var})}, ${__test_func5( ${__test_func4("${int_var}", "func4")}, ${__test_func3(\'${__test_func2("func2", True)}\', \'func3\')} )})}')) # 返回 var: unknown function:
#调用输出:
#-----func6 called-----
#arg1: shouke arg2: 3
#
#-----func4 called-----
#arg1: 3 arg2: func4
#
#-----func2 called-----
#arg1: func2 arg2: True
#
#-----func3 called-----
#arg1: func2 arg2: func3
#
#-----func5 called-----
#arg1: 9.99 arg2: 999
#
#-----func7 called-----
#arg0 = False
#arg1 = ['e1', 'e2']
#-----func2 called-----
#arg1: func2 arg2: True
#
#-----func4 called-----
#arg1: 3 arg2: func4
#
#-----func2 called-----
#arg1: func2 arg2: True
#
#-----func2 called-----
#arg1: func2 arg2: True
#
#-----func2 called-----
#arg1: func2 arg2: True
#
#-----func2 called-----
#arg1: func2 arg2: True
#

print(evaluate_dynamic_value('${ __test_func7(set())}'))
#调用输出:
# -----func7 called-----
# arg0 = {1, 2, 3}
来源:https://www.cnblogs.com/shouke/p/17843050.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: Python 按规则解析并替换字符串中的变量及函数