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

这篇具有很好参考价值的文章主要介绍了Python 按规则解析并替换字符串中的变量及函数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

需求

1、按照一定规则解析字符串中的函数、变量表达式,并替换这些表达式。这些函数表达式可能包含其它函数表达式,即支持函数嵌套

2、函数表达式格式:${ __函数名称() }、${__函数名称( 函数参数 )}

3、变量表达式格式:${ varName }

注意:文章来源地址https://www.toymoban.com/news/detail-746841.html

  1. 函数名称以__打头
  2. ${ 之间不能有空格
  3. 函数名称和函数的左括号 ( 之间不能有空隔
  4. 函数支持嵌套,形如:${ __function1( ${__function2()} )}
  5. 函数参数如果是字符串(包括由嵌套函数返回值),需要使用单引号、双引号引用 形如 ${ __function1( "str_value", 123)}${ __function1(key="arg_value")}${ __function1(key=\'arg_value\')}
  6. 函数参数支持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 按规则解析并替换字符串中的变量及函数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • chatgpt赋能python:Python中如何取出字符串中的数字并赋予新的变量

    在 Python 中,我们经常需要处理字符串,其中可能包含多种类型的数据。当我们需要获取字符串中的数字时,该怎样做呢?本文将介绍取出字符串中的数字的方法,并赋予新的变量,以便后续使用。 第一种方法是使用循环遍历字符串,将字符串中的每个字符逐一比较,如果是

    2024年02月08日
    浏览(45)
  • 【833. 字符串中的查找与替换】

    来源:力扣(LeetCode) 描述: 你会得到一个字符串 s (索引从 0 开始),你必须对它执行 k 个替换操作。替换操作以三个长度均为 k 的并行数组给出: indices , sources , targets 。 要完成第 i 个替换操作: 检查 子字符串 sources[i] 是否出现在 原字符串 s 的索引 indices[i] 处。 如果没有

    2024年02月13日
    浏览(44)
  • LeetCode 0833. 字符串中的查找与替换

    力扣题目链接:https://leetcode.cn/problems/find-and-replace-in-string/ 你会得到一个字符串 s  (索引从 0 开始),你必须对它执行 k 个替换操作。替换操作以三个长度均为 k 的并行数组给出: indices ,  sources ,   targets 。 要完成第 i 个替换操作: 检查 子字符串   sources[i]  是否出现在 原字

    2024年02月12日
    浏览(42)
  • 【代码随想录 | Leetcode | 第十一天】字符串 | 反转字符串 | 反转字符串 II | 替换空格 | 反转字符串中的单词 | 左旋转字符串

    欢迎来到小K的Leetcode|代码随想录|专题化专栏,今天将为大家带来字符串~反转字符串 | 反转字符串 II | 替换空格 | 反转字符串中的单词 | 左旋转字符串的分享 ✨ ✨题目链接点这里 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要

    2024年02月15日
    浏览(52)
  • C++string类replace()函数(替换字符串中的子串)

    C++中的string类提供了replace()函数,用于替换字符串中的子串。其函数原型如下: 其中,pos表示要替换的子串在原字符串中的起始位置,len表示要替换的子串的长度,str表示用来替换的字符串。 replace()函数的使用方法非常简单,只需要传入要替换的子串的位置、长度和替换字

    2024年02月05日
    浏览(55)
  • Python字符串替换的3种方法

    Python字符串替换笔记主要展示了如何在Python中替换字符串。Python中有以下几种替换字符串的方法,本文主要介绍前三种。 replace方法(常用) translate方法 re.sub方法 字符串切片(根据Python字符串切片方法替换字符) Python replace方法把字符串中的old(旧字符串) 替换成new(新字符

    2024年02月05日
    浏览(41)
  • 替换空格&&反转字符串中的单词(LeetCode 剑指offer05 && 151)

    题目 剑指 Offer 05. 替换空格  思路 遍历,使用新的字符串来接原字符串,如为空格,则加入%20,否则加入原字符串。  不过看了题解有另一种解法,由于空格转化为%20,设计到原字符存储空间的增加,因此先计算出需要增加的空间后。再使用双指针,从后往前遍历,这里画的

    2024年02月16日
    浏览(46)
  • 2023-08-15 LeetCode每日一题(字符串中的查找与替换)

    点击跳转到题目位置 你会得到一个字符串 s (索引从 0 开始),你必须对它执行 k 个替换操作。替换操作以三个长度均为 k 的并行数组给出:indices, sources, targets。 要完成第 i 个替换操作: 检查 子字符串 sources[i] 是否出现在 原字符串 s 的索引 indices[i] 处。 如果没有出现, 什么

    2024年02月12日
    浏览(43)
  • Python replace()函数使用详解,Python替换字符串

    「作者主页」: 士别三日wyx 「作者简介」: CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」: 小白零基础《Python入门到精通》 replace() 可以 「替换」 字符串中的内容 语法 参数 old :(必选,字符串类型)被替换的字符串 new :(必选,

    2024年02月16日
    浏览(47)
  • vue实现把字符串中的所有@内容,替换成带标签的

    前言:         目前有个需求是,要把输入框里面的@还有姓名高亮。 要求: 1、必须用 v-html ,带标签的给他渲染 2、把字符串中的@全部查找出来,替换掉,注意要过滤已经替换好的,不然就是无限循环了 实现方法:

    2024年02月11日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包