Python?按規(guī)則解析并替換字符串中的變量及函數(shù)(示例代碼)
按規(guī)則解析并替換字符串中的變量及函數(shù)
需求
1、按照一定規(guī)則解析字符串中的函數(shù)、變量表達式,并替換這些表達式。這些函數(shù)表達式可能包含其它函數(shù)表達式,即支持函數(shù)嵌套
2、函數(shù)表達式格式:${ __函數(shù)名稱() }、${__函數(shù)名稱( 函數(shù)參數(shù) )}
3、變量表達式格式:${ varName }
注意:
- 函數(shù)名稱以
__
打頭 ${
之間不能有空格- 函數(shù)名稱和函數(shù)的左括號
(
之間不能有空隔 - 函數(shù)支持嵌套,形如:
${ __function1( ${__function2()} )}
- 函數(shù)參數(shù)如果是字符串(包括由嵌套函數(shù)返回值),需要使用單引號、雙引號引用 形如
${ __function1( "str_value", 123)}
,${ __function1(key="arg_value")}
,${ __function1(key=\'arg_value\')}
, - 函數(shù)參數(shù)支持python原生函數(shù) 形如
${ __function1( set([1,2,3]) )}
實現(xiàn)代碼
#!/usr/bin/env python # -*- coding:utf-8 -*- import re REGEX_PATTERN_FOR_DYNAMIC = re.compile('(\${\s*.+\s*})', re.DOTALL) # 用于獲取動態(tài)值中的表達式 REGEX_PATTERN_FOR_VAR = re.compile('(\${\s*[^{}]+s*})', re.DOTALL) # 用于獲取動態(tài)值中的變量表達式 REGEX_PATTERN_FOR_FUNC_DEFINITION = re.compile('\${\s*__.+?\(.*?\)\s*}', re.DOTALL) # 用于獲取函數(shù)表達式中的函數(shù)名稱及其參數(shù) REGEX_PATTERN_FOR_FUNC_NAME_WITH_ARGS = re.compile('\${\s*(__.+?)\((.*?)\)\s*}', re.DOTALL) # 用于獲取函數(shù)表達式中的函數(shù)名稱及其參數(shù) 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): '''解析動態(tài)值 @params: dynamic_value 動態(tài)值,如果是字符串類型,帶雙引號、單引號 ''' 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('__'): # 函數(shù) 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): # 替換后的動態(tài)值,還是可能存在動態(tài)值 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() }')) #調(diào)用輸出: #-----func1 called----- print(evaluate_dynamic_value('${ __test_func2("user", "shouke") }')) # 輸出:func2 #調(diào)用輸出: #-----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 # 調(diào)用輸出: #-----func1 called----- #-----func2 called----- #arg1: user arg2: shouke # print(evaluate_dynamic_value('${ __test_func7("addr", "sz") }')) #-----func7 called----- #調(diào)用輸出: #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"]) }')) #調(diào)用輸出: # -----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})}')) #調(diào)用輸出: #-----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: #調(diào)用輸出: #-----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]))}')) #調(diào)用輸出: # -----func7 called----- # arg0 = {1, 2, 3}
到此這篇關(guān)于Python 按規(guī)則解析并替換字符串中的變量及函數(shù)的文章就介紹到這了,更多相關(guān)Python 替換字符串變量及函數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
flask post獲取前端請求參數(shù)的三種方式總結(jié)
這篇文章主要介紹了flask post獲取前端請求參數(shù)的三種方式總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12python數(shù)據(jù)預(yù)處理之數(shù)據(jù)標準化的幾種處理方式
這篇文章主要介紹了python數(shù)據(jù)預(yù)處理之數(shù)據(jù)標準化的幾種處理方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-07-07python TinyDB輕量級文檔導向數(shù)據(jù)庫輕松存儲訪問
這篇文章主要為大家介紹了python TinyDB輕量級文檔導向數(shù)據(jù)庫輕松存儲訪問數(shù)據(jù)使用探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2024-01-01numpy求矩陣的特征值與特征向量(np.linalg.eig函數(shù)用法)
這篇文章主要介紹了numpy求矩陣的特征值與特征向量(np.linalg.eig函數(shù)用法),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02Python強制重新安裝Python包之pip的高級使用技巧
這篇文章主要介紹了如何使用pip強制重新安裝Python包的幾種方法,包括使用--upgrade、--force-reinstall和--no-deps選項,這些方法可以幫助解決包損壞、依賴問題或其他需要重新安裝包的情況,需要的朋友可以參考下2025-03-03對numpy下的軸交換transpose和swapaxes的示例解讀
今天小編就為大家分享一篇對numpy下的軸交換transpose和swapaxes的示例解讀,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-06-06