1、按照一定规则解析字符串中的函数表达式,并替换这些表达式。这些函数表达式可能包含其它函数表达式,即支持函数嵌套
2、函数表达式格式:${ ?__函数名称() ?}、${__函数名称( 函数参数 )}
注意:
1、先解析内部函数,再解析其父函数,即从内到外解析
实现方式:查找不包含嵌套函数表达式的函数表达式,先临时替换为“临时插件函数表达式” 形如 ‘@plugin_func_custom_function_name@‘,同时以该值为字典key,存储对应临时函数表达式,然后再用替换后的字符串去查找不包含嵌套函数表达式的函数表达式,然后再替换字符串,直到找不到为止
2、解析替换后的字符串,获取“临时插件函数表达式”,然后执行调用该函数
3、函数参数类型分析
字符串参数要求用 单、双引号 引用,通过eval(参数)转换,如果转换成功则用转换后的,否则用转换前的
#!/usr/bin/env?python
#?-*-?coding:utf-8?-*-
#
import?re
#?插件函数样例
def?base64(*args,?**kwargs):
????print(‘base64?called‘)
????print(‘args:‘,?args)
????print(‘kwargs:‘,?kwargs)
????return?1
def?read_file(*args,?**kwargs):
????print(‘fread_file?called‘)
????print(‘args:‘,?args)
????print(‘kwargs:‘,?kwargs)
????return?[‘a‘,?1]
def?generate_num(*args,?**kwargs):
????print(‘generate_num?called‘)
????print(‘args:‘,?args)
????print(‘kwargs:‘,?kwargs)
????return?899999
PUGIN_FUNC_MAP?=?{‘read_file‘:read_file,?‘base64‘:base64,?‘generate_num‘:generate_num}?#?存放插件函数名称和对应函数实体的映射
func_map?=?{}?#?存放程序执行过程中,获取的临时函数名称和函数表达式的映射关系
REG_FOR_TEMP_PLUGIN_FUNC?=?re.compile(‘@(plugin_func.+?)@‘,?re.DOTALL)?#?用于查找临时插件函数名称?形如?[‘‘@plugin_func__base64@‘,‘@plugin_func__read_file@‘]
REG_FOR_FUNC_NAME_OF_EXP??=?re.compile(‘\${\s*(_.+?)\(‘,?re.DOTALL)?#?用于查找函数表达式中的函数名称
REG_FOR_FUNC_NAME_AND_ARGS?=?re.compile(‘\${\s*(_.+?)\((.*?)\)\s*}‘,?re.DOTALL)?#?用于查找函数表达式中的函数定义(函数名称及其参数)
REG_FOR_STRICT_FUNC_EXP?=?re.compile(‘\${\s*_.+\(.*?\)\s*}‘,?re.DOTALL)?#?用于获取严格函数定义表达式
REG_FOR_KWARG?=?re.compile(‘^[^"\‘]+[^"\‘]+\s*=\s*.+‘,?re.DOTALL)?#?用于匹配关键词参数
def?_replace_function(string):
????‘‘‘替换字符串中的插件参数‘‘‘
????string?=?string.strip()
????func_name_list?=?REG_FOR_TEMP_PLUGIN_FUNC.findall(string)?#?获取函数名称列表?形如?[‘‘@plugin_func__base64@‘,‘@plugin_func__read_file@‘]
????if?len(func_name_list)?==?1?and?string?==?‘@%s@‘?%?func_name_list[0]:?#?整个字符串就是一个函数表达式,字符串代表的值的类型和函数返回值类型相同,如果函数不存在,返回None
????????if?func_name_list[0]?in?func_map:
????????????return?call_plugin_func(func_map.get(func_name_list[0]))
????else:
????????for?func_name?in?func_name_list:
????????????if?func_name?in?func_map:
????????????????string?=?string.replace(‘@%s@‘?%?func_name,?str(call_plugin_func(func_map.get(func_name))))
????????return?string
def?call_plugin_func(function_express):
????‘‘‘
????调用插件函数
????‘‘‘
????try:
????????result?=?REG_FOR_FUNC_NAME_AND_ARGS.findall(function_express)?#?查找函数表达式中的函数定义(函数名称及其参数)
????????if?result:
????????????plugin_func_name,?plugin_func_args?=?result[0]
????????????plugin_func_name?=?plugin_func_name.strip(‘_‘)?#?去掉函数前缀标识?_?以获取真正的函数
????????????plugin_func_args?=?plugin_func_args.strip()
????????????plugin_func_arg_list?=?[]
????????????if?plugin_func_args:
????????????????plugin_func_arg_list?=?plugin_func_args.split("||")?#?函数参数要求用?||?分隔
????????????position_arg_list?=?[]?#?存放位置参数
????????????keyword_arg_dict?=?{}??#?存放关键词参数
????????????for?item?in?plugin_func_arg_list:
????????????????item?=?item.strip()
????????????????if?REG_FOR_KWARG.findall(item):?#?关键词参数
????????????????????key,?value?=?re.split(‘\s*=[=|\s]*‘,?item)
????????????????????try:
????????????????????????value?=?_replace_function(value)
????????????????????????keyword_arg_dict[key.strip()]?=?eval(value)
????????????????????except?Exception?as?e:
????????????????????????keyword_arg_dict[key.strip()]?=?value
????????????????else:
????????????????????try:
????????????????????????value?=?_replace_function(item)
????????????????????????position_arg_list.append(eval(value))
????????????????????except?Exception?as?e:
????????????????????????position_arg_list.append(value)
????????????if?plugin_func_name?in?PUGIN_FUNC_MAP:
????????????????return?PUGIN_FUNC_MAP.get(plugin_func_name)(*position_arg_list,?**keyword_arg_dict)
????????????else:
????????????????return?None
????????else:?#未找到函数
????????????print(‘没有找到同函数表达式(?%s?)匹配的函数定义‘?%?function_express)
????????????return?None?#
????except?Exception?as?e:
????????raise
def?replace_function(string):
????‘‘‘替换函数‘‘‘
????try:
????????regular_obj?=?re.compile(‘\${\s*(_.+?)\(‘,?re.DOTALL)
????????#?获取临时函数名称
????????temp_func_name_list?=?REG_FOR_FUNC_NAME_OF_EXP.findall(string)
????????string_copy?=?string
????????old_func_name_set?=?set()?#?存放上一次的查找结果
????????while?old_func_name_set?!=?set(temp_func_name_list):
????????????old_func_name_set?=?set(temp_func_name_list)
????????????for?func_name?in?temp_func_name_list:?#?遍历查找函数对应的函数表达式
????????????????pattern?=?‘\${\s*%s\(.*?\)\s*}‘?%?func_name
????????????????func_express_list?=?re.findall(pattern,?string_copy)?#?获取函数表达式(因为可能存在函数嵌套,所以获取的表达式可能是错误的)
????????????????if?not?func_express_list:?#?找不到函数表达式,说明该函数名称无效,不合法
????????????????????continue
????????????????for?func_express?in?func_express_list:
????????????????????temp_func_express?=?func_express.strip().lstrip(‘${‘)
????????????????????if?not?REG_FOR_STRICT_FUNC_EXP.findall(temp_func_express):?#?表达式不包含嵌套函数,则??获取正确的函数表达式进行替换
????????????????????????right_func_express_list?=?REG_FOR_STRICT_FUNC_EXP.findall(func_express)
????????????????????????for?right_func_express?in?right_func_express_list:
????????????????????????????string_copy?=?string_copy.replace(right_func_express,?‘@plugin_func%s@‘?%?func_name)
????????????????????????????func_map[‘plugin_func%s‘?%?func_name]?=?right_func_express?#?建立临时函数名称和函数表达式的映射关系
????????????temp_func_name_list?=?re.findall(regular_obj,?string_copy)
????????if?string_copy?==?string:?#?无变化
????????????return?string
????????return?_replace_function(string_copy)
????except?Exception?as?e:
????????print(‘替换函数出错%s‘?%?e)
????????return?string
#?运行测试
src_string?=?"some?string?${?__base64(?${__read_file(‘filepath‘)}?||?‘string_arg‘?||?‘b==整个表达式(包括b==)是字符串参数‘?||?‘支持单双引号转义字符参数\"?||?‘fake_key_arg1?=?我整个表达式都是字符串参数‘?||?key_arg1=‘关键词字符串参数‘||key_arg2=1?||key_arg3=[1,?2,?3]?||?key_arg4={‘a‘:1,?‘b‘:‘字典参数‘}?)?}?hello"
print(replace_function(src_string))
src_string?=??‘${?__generate_num()?}‘
print(replace_function(src_string))运行结果如下
原文:https://blog.51cto.com/shouke/2856285