Python 按规则解析并替换字符串中的变量及函数
按规则解析并替换字符串中的变量及函数
需求
1、按照一定规则解析字符串中的函数、变量表达式,并替换这些表达式。这些函数表达式可能包含其它函数表达式,即支持函数嵌套
2、函数表达式格式:${ __函数名称() }、${__函数名称( 函数参数 )}
3、变量表达式格式:${ varName }
注意:
- 函数名称以
__打头 ${之间不能有空格- 函数名称和函数的左括号
(之间不能有空隔 - 函数支持嵌套,形如:
${ __function1( ${__function2()} )} - 函数参数如果是字符串(包括由嵌套函数返回值),需要使用单引号、双引号引用 形如
${ __function1( "str_value", 123)},${ __function1(key="arg_value")},${ __function1(key=\'arg_value\')}, - 函数参数支持python原生函数 形如
${ __function1( set([1,2,3]) )}
实现代码
#!/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[2:-1].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", '
'[1, 3, 5], '
'["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 = [1, 3, 5]
# 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([1, 2, 3]))}'))
#调用输出:
# -----func7 called-----
# arg0 = {1, 2, 3}
Python 按规则解析并替换字符串中的变量及函数的更多相关文章
- 《Python CookBook2》 第一章 文本 - 替换字符串中的子串
替换字符串中的子串 任务: 给定一个字符串,通过查询一个字符串替换字典,将字符串中被标记的子字符串替换掉. 解决方案: >>> import string >>> ...
- PHP字符串中的变量解析(+教你如何在PHP字符串中加入变量)
定义字符串的时候,用单引号或者双引号都是可以的.我个人习惯是用双引号.在输出字符串的时候,若字符串中含有字符串变量,使用单引号和双引号则是有区别的.如下面程序: 1 2 3 4 5 6 7 8 < ...
- python3 替换字符串中指定位置字符
大家都知道字符串在python中是不可变数据类型,那么我们如何替换字符串中指定位置的字符呢? 字符串转换列表替换并转换解决: def replace_char(string,char,index): ...
- PHP 自定义字符串中的变量名解析
PHP 自定义字符串中的变量名解析 这样一个需求:页面的 title 可以在后台自定义,自定义内容中可能包含变量,变量用 {$var} 表示, 其中 $var 为变量名 将 title 字段存入数 ...
- js替换字符串中的数字或非数字
替换字符串中的数字 var text = "abc123"; text=text.replace(/[0-9]/ig,""); 此时得到的text为" ...
- JavaScript替换字符串中最后一个字符
1.问题背景 在一个输入框中,限制字符串长度为12位.利用键盘输入一个数字,会将字符串中最后一位替换,比方:111111111111.再输入一个3,会显示111111111113 2.详细实现 < ...
- 正则表达式替换字符串中的html标签
正则表达式替换字符串中的html标签 ··· var newStr = str.replace(/<[^>]+>/g, ''); ···
- Python之word文档替换字符串(也可以用于短模板套用)
Python之word文档替换字符串(也可以用于短模板套用),代码如下: 1 ''' 2 #word模板套用1:创建模板,适合比较短的文档 3 ''' 4 5 #导入所需库 6 from docx i ...
- js如何替换字符串中匹配到多处中某一指定节点?
抛出一个问题,如图,搜索关键字,匹配到四处,那我鼠标放在第二处,我想把它变个颜色,该怎么实现呢?回到文章的标题,js如何替换字符串中匹配到多处中某一指定节点? 字符串的替换,我们首先想到的一个属性是r ...
- php基础10:字符串中插入变量
<?php //插入字符串 //1.双引号可以解析字符串中的变量:但是前后不能跟中文符号 $username = "gaoxiong"; echo "my name ...
随机推荐
- golang 接口动态派发性能问题
测试代码 package main type Duck interface { Quack() } type Cat struct { Name string } //go:noinline func ...
- 关于Zotero组件在office word中的添加
引言:学姐问我,怎么弄Zotero,在调试过程中遇到的问题及解决方案 Q&A Zotero的安装 找到官网(https://www.zotero.org/)点击download,安装(个人觉得 ...
- 7.12考试总结(NOIP模拟12)[简单的区间·简单的玄学·简单的填数]
即使想放弃,也没法放弃最想要的东西,这就是人 前言 这次应该是和 SDFZ 一起打的第一场比赛吧. 然而我还是 FW 一个... 这次考试也有不少遗憾,主要的问题是码力不足,不敢去直面正解,思考程度不 ...
- 一个问题:六位八段数码管(Verilog)
[基本信息] 需求:verilog程序,显示任意六位字符或数值,包含点号,且能够按需点亮位数.(学习篇) 芯片型号:cyclone Ⅳ EP4CE10F17C8 数码管属性:六位.八段 [最终成果图] ...
- C++笔记(9) 异常
程序有时会遇到运行阶段错误,导致程序无法正常走下去.对于这种问题,处理方法主要有: 1.调用abort() Abort()函数原型位于头文件cstdlib,其典型实现是向标准错误流(即cerr使用的错 ...
- Qt添加资源文件
参考视频:https://www.bilibili.com/video/BV1XW411x7NU?p=27 以添加图片为例进行说明: 1)点击工程名,选择"添加新文件": 2)选择 ...
- Scrapy框架(三)--全站数据爬取
scrapy基于Spider类的全站数据爬取 大部分的网站展示的数据都进行了分页操作,那么将所有页码对应的页面数据进行爬取就是爬虫中的全站数据爬取.基于scrapy如何进行全站数据爬取呢?1.将每一个 ...
- undefined,null 和 undeclared 有什么区别?
a.null表示"没有对象",即该处不应该有值,转为数值时为0.典型用法是:作为函数的参数,表示该函数的参数不是对象.作 为对象原型链的终点. b.undefined表 ...
- Linux/Unix-stty命令详解
文章目录 介绍 stty命令的使用方法 stty的参数 我常用的选项 所有选项 介绍 stty用于查询和设置当前终端的配置. 如果你的终端回车不换行.输入命令不显示等各种奇葩问题,那么stty命令可以 ...
- 李沐多模态串讲视频总结 ALBEF VLMo BLIP CoCa BEITv3 模型简要介绍
开场 多模态串讲的上篇是比较传统的多模态任务 多模态最后的模态交互很重要 传统的缺点是都用了预训练的目标检测器,训练和部署都很困难. ViLT 把预训练的目标检测器换成了一层的 Patch Embed ...