能否使用Jinja2模板从文档中反向工程参数?

7
Jinja2 的一般工作流程是 参数 + Jinja2 模板 = 生成的文档
from jinja2 import Template
t = Template("Hello {{ something }}!")
t.render(something="World")
>>> u'Hello World!'

是否可以使用Jinja2模板来逆向工程化文档中的参数?换句话说,我正在寻找以下内容:Jinja2模板+生成的文档=参数

from jinja2 import Template
t = Template("Hello {{ something }}!")
t.reverse("Hello World!")
>>> {"something" : "World"}

json输出不是必需的,但它会很方便。

如果不使用json,有什么好的方法来创建这样的逻辑呢?

背景: 我使用Jinja2生成Cisco交换机配置文件,能够查看以前生成的文档将是一个不错的功能,与其显示1000+行的配置脚本,我更想列出参数。我知道可以通过将所有参数存储在简单的数据库中来解决这个问题,但目前我还没有设置数据库,并且如果可能的话,我希望避免使用它。


请查看以下两个帖子:这个这个。这是您正在寻找的吗? - vrs
@vrs 感谢您的快速回复,我已经看过那些帖子了。我已经编辑了我的问题,并提供了一些示例,这可能有助于理解我的具体情况。 - Balázs Hajdu
我认为这通常是不可能的。你的用例是什么? - syntonym
2
对模板和渲染后的模板进行diff操作可以显示出替换内容。 - totoro
1
我使用Jinja2生成Cisco交换机配置文件,如果能够查看以前生成的文档并仅列出参数而不是显示1000多行的配置脚本,那将是一个很好的功能。我知道可以通过将所有参数存储在简单的数据库中来解决这个问题,但目前我没有设置数据库,并且我想避免使用它。 - Balázs Hajdu
显示剩余4条评论
4个回答

1
如果有人仍然感兴趣或者关注这个问题,我认为该库(在2021年发布)基本上可以完成这项工作(或者被用来完成这项工作):

parse() 是 format() 的反操作。

https://pypi.org/project/parse/

可以定义一个模式(类似于模板),并将字符串输入以返回参数。
基于原始问题的最小工作示例:
import parse
pattern = parse.compile("Hello {something}")
result = pattern.parse("Hello world")
result["something"]
>>> 'world'

0

这个开源项目似乎提供了所需的功能: https://github.com/yvdlima/pytemplate-reverse

使用示例:

from template_reverse import ReverseTemplate

segments = [
    "shrek3_0_600.avi",
    "shrek3_1_560.avi",
    "shrek3_2_780.avi"
]
rt = ReverseTemplate("{video_name}_{segment_id}_{segment_duration_in_secs}.avi")

total_duration = 0

for segment in segments:
    values = rt.reverse(segment)
    print("Checking out movie", values["video_name"], "part ", values["segment_id"])
    total_duration += int(values["segment_duration_in_secs"])

print("Total video duration so far", total_duration)

0

这个可以工作,但它并没有提供所有的信息。

import textfsm
import tempfile
import re
import pprint

j2template = open(<template_file_path>)

find_txt = '(\{\{.+?\}\})'
all_variables = re.findall(find_txt, j2template.read())
variable_set = set()

for variable in all_variables:
    variable_set.add( variable )

value_block_txt = ''
for value in variable_set:
    value = value.replace('.', '')
    value_block_txt += "Value List {val_text} (\S+)\n".format(val_text = value.strip('{}\ '))

fsm_regex_block = '''
Start
'''
j2template = open(<filepath>)
for line in j2template.readlines():
    replace_list = [var for var in variable_set if(var in line)]
    if len(replace_list) > 0: 
        for string in replace_list:
                line = line.replace(string, "${"+string.replace('.', '').strip('{}. ')+"}") 
        line = "  ^"+line
        fsm_regex_block += line

textfsm_template = value_block_txt
textfsm_template += fsm_regex_block

f = open(<temp_file_path>, 'w+')
f.write(textfsm_template)
f.close()

fsm = textfsm.TextFSM(open(<temp_file_path>))
original_variables_list_of_lists = fsm.ParseText(jinja_device_config_output)

print(original_variables_list_of_lists)

os.unlink(f)
Outputs a list of lists like: [[['1', '1', '1'], ['12'], ['abcd.1234.0000'], ['1', '1', '12'], ['CGNLTEST123V', 'CGNLTEST123V', 'CGNLTEST123V', 'CGNLTEST123V', 'CGNLTEST123V', 'CGNLTEST123V', 'CGNLTEST123V', 'CGNLTEST123V', 'CGNLTEST123V', 'CGNLTEST123V', 'CGNLTEST123V', 'CGNLTEST123V'], ['fe81:::::/127']]]

然后,我将为每个变量的输入参数列表进行去重,以获取原始值。


0

这个可以工作,但它只是提取所有参数。它不会给你顺序或它们之间的关系:

import textfsm
import tempfile
import re
import pprint

j2template = open(<template_file_path>)

find_txt = '(\{\{.+?\}\})'
all_variables = re.findall(find_txt, j2template.read())
variable_set = set()

for variable in all_variables:
    variable_set.add( variable )
    
value_block_txt = ''
for value in variable_set:
    value = value.replace('.', '')
    value_block_txt += "Value List {val_text} (\S+)\n".format(val_text = value.strip('{}\ '))

fsm_regex_block = '''
Start
'''
j2template = open(<filepath>)
for line in j2template.readlines():
    replace_list = [var for var in variable_set if(var in line)]
    if len(replace_list) > 0: 
        for string in replace_list:
                line = line.replace(string, "${"+string.replace('.', '').strip('{}. ')+"}") 
        line = "  ^"+line
        fsm_regex_block += line
        
textfsm_template = value_block_txt
textfsm_template += fsm_regex_block

f = open(<temp_file_path>, 'w+')
f.write(textfsm_template)
f.close()

fsm = textfsm.TextFSM(open(<temp_file_path>))
original_variables_list_of_lists = fsm.ParseText(jinja_device_config_output)

print(original_variables_list_of_lists)

os.unlink(f)

输出一个类似于列表的列表:

[
    [
        ['1', '1', '1'],
        ['12'],
        ['abcd.1234.0000'],
        ['1', '1', '12'],
        [
            'CGNLTEST123V', 
            'CGNLTEST123V', 
            'CGNLTEST123V', 
            'CGNLTEST123V', 
            'CGNLTEST123V', 
            'CGNLTEST123V', 
            'CGNLTEST123V', 
            'CGNLTEST123V', 
            'CGNLTEST123V', 
            'CGNLTEST123V', 
            'CGNLTEST123V', 
            'CGNLTEST123V'
            ],
        [
            'fe81:::::/127'
        ]
    ]
]

您可以对每个变量的输入参数列表进行去重,以获取原始值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接