从字符串中提取模板(一种模式)并使用此模式解析其他字符串。
项目描述
介绍
给定一些字符串(或文件),这个库在它们之间提取一个公共模板(方法learn)——有些人称之为“反向模板”。创建模板后,您可以使用它解析其他字符串/文件 - parse方法将仅返回此文件中的更改(“空白”)。它的作用与模板库(例如 Jinja)的作用相反。但目前,它只能识别固定变量(例如,它不能创建for和if块)。
如果您有模板和“空白”,您还可以使用join方法填充空白- 它会返回一个填充了模板的字符串。还有一些其他功能:
如果您不想/不需要Templater(主类)为您创建模板,您可以传递一个预处理模板(手动创建或在使用learn之前创建并保存在某处)。
您可以拆分学习和解析过程,因为学习过程通常执行一次,并且与解析过程相比需要大量时间。为了方便这个过程,Templer有方法dump、 save、load和open,因此您可以学习和保存模板定义,以便以后加载和解析您想要的次数(您也可以加载、了解更多和保存)。
templater易于使用,易于学习,并且为您完成了艰苦的工作(例如:为了提高性能,部分学习算法是用 C 实现的)。你有5分钟吗?因此,通过示例学习。
安装
模板程序在 PyPI 中可用,因此安装它就像执行一样简单:
pip install templater3
或者您可以下载最新版本并使用setup.py进行安装:
git clone https://github.com/Lee-W/templater cd templater python setup.py build install
术语
我们应该在这里明确一些定义/概念:
Template:整个对象(Templater的实例)。
文档:具有某种模式的字符串或文件。您将使用文档使模板对象学习和识别这些模式,因此稍后您可以使用模板对象解析文档并仅获取非“静态”信息。
块:模板的固定部分。运行学习时可以更改(数量和大小)。
空白:也称为孔或变量,空白是模板中在具有相同模板的文档之间更改的部分。
模板定义:存储在定义它的模板中的信息(它是一个 Python 列表,具有非常简单的语法,描述了模板是如何组成的)。
标记:当你想保存一个模板时,应该在块之间放置一些东西来“标记”空白(这样模板定义可以在以后重建)。
命名标记:一个标记加上一个标头称为命名标记。它们方便且更易读,因为您可以通过名称而不是索引访问“空白”。
怀疑?别担心,看看例子,你会明白的。
例子
您需要知道的全部内容如下(以及示例目录中):
>>> from templater import Templater
>>> documents_to_learn = ['<b> spam and eggs </b>', '<b> ham and spam </b>',
'<b> white and black </b>'] # list of documents
>>> template = Templater()
>>> for document in documents_to_learn:
... template.learn(document)
...
>>> print('Template created:', template._template # template definition)
Template created: [None, '<b> ', None, ' and ', None, ' </b>', None]
>>> document_to_parse = '<b> yellow and blue </b>'
>>> print('Parsing other document:', template.parse(document_to_parse))
Parsing other document: ['', 'yellow', 'blue', '']
>>> print('Filling the blanks:', template.join(['', 'red', 'orange', '']))
Filling the blanks: <b> red and orange </b>
您可以将预处理模板作为列表传递(空白是None,块是字符串):
>>> t2 = Templater(template=[None, 'Music: ', None, ', Band: ', None]) >>> print(t2.join(['', 'Welcome to the Jungle', 'Guns and Roses'])) Music: Welcome to the Jungle, Band: Guns and Roses
…或者您可以传递带有标记的字符串,然后Templater将为您创建列表:
>>> t3 = Templater(template='language=#,cool=#', marker='#') >>> print(t3.join(['', 'Python', 'YES', ''])) language=Python,cool=YES
保存和打开模板很容易:
>>> template.save('my-first-template.html', marker='|||')
>>> # and some time later...
>>> loaded_template = Templater.open('my-first-template.html', marker='|||')
>>> print(loaded_template.parse('<b> Romeo and Juliet </b>'))
['', 'Romeo', 'Juliet', '']
save和dump的区别在于save存储模板字符串,用标记填充空白,而dump用cPickle保存整个 Templater对象。对是:
保存并打开(用标记填充的原始模板字符串)
加载和转储(整个对象)
注意:保存总是在文件末尾添加一个\n;load 删除文件末尾的尾随\r\n或\n(如果有)。
注意 2:当传递一个预处理模板(使用Templater 初始化程序或Templater.open)时,请确保它以标记开始和结束。
如果你得到很多空白,你可以配置学习过程:只需调整min_block_size - 这是允许在模板中创建新块的最小字符数:
>>> str_1 = 'my favorite color is blue' >>> str_2 = 'my favorite color is violet' >>> t = Templater() # default min_block_size = 1 >>> t.learn(str_1) >>> t.learn(str_2) >>> print(t._template) [None, 'my favorite color is ', None, 'l', None, 'e', None]
我们不想要那个“l”和“e”,对吧?所以:
>>> t = Templater(min_block_size=2) >>> t.learn(str_1) >>> t.learn(str_2) >>> print(t._template) [None, 'my favorite color is ', None]
您还可以在模板中添加“标题”-标题将是标记的名称,因此您将拥有一个带有命名标记的模板,并且parse将返回一个dict而不是list。它比使用列表索引更清晰,让我们看看:
>>> import re
>>> # Let's create a regexp that cases with '{{var}}' (it'll be our marker)
>>> regexp_marker = re.compile(r'{{([a-zA-Z0-9_-]*)}}')
>>> template = Templater('{{first-var}}<b>{{second-var}}</b>{{third-var}}',
marker=regexp_marker)
>>> # The template knows the name of each marker just using the regexp provided
>>> # Passing marker as regexp to specify named markers also work for Templater.open
>>> print(template.parse('This <b> is </b> a test.'))
{'second-var': ' is ', 'third-var': ' a test.', 'first-var': 'This '}
>>> # To save the template with named markers we need to provide a Python string.
>>> # Templater will call .format() of this string for each marker with its name
>>> template.save('template-with-named-markers.html', marker='--{}--')
>>> # Will save '--first-var--<b>--second-var--</b>--third-var--\n'
如果您有一个没有标题的模板,只需使用add_headers 方法添加到它:
>>> t = Templater('+<tr><td>+</td><td>+</td></tr>+', marker='+')
>>> t.parse('<tr><td>hello</td><td>world</td></tr>')
['', 'hello', 'world', '']
>>> t.add_headers(['before', 'first-column', 'second-column', 'after'])
>>> t.parse('<tr><td>hello</td><td>world</td></tr>')
{'after': '', 'before': '', 'first-column': 'hello', 'second-column': 'world'}
注意:命名标记有一个问题:如果使用它们,您将无法运行学习。
笔记
我真的很想知道你是否在使用这个项目,你对它的印象是什么。如果您对功能有新想法、发现错误或只想说“谢谢,我正在使用它!”,请 通过 gmail 的 alvarojusten与我联系。
如果你想编写一些东西,只需在 GitHub 上 fork并创建一个拉取请求。为您提供的一些技术说明:
该项目使用测试驱动开发。
测试在 macOS 10.14.4 上使用 Python 3.6 运行。
您可以在 CHANGELOG.rst中查看版本之间的更改。
该项目使用语义版本控制(感谢 Tom Preston-Werner)。