正则表达式匹配液体代码

时间:2016-07-10 15:37:54

标签: python html regex liquid

我正在使用Jekyll建立一个网站我想从给定的HTML文件中自动删除液体代码(和液体代码)。我是用Python使用正则表达式做的,到目前为止我有这个:

\{.*?\}|\{\{.*?\}\}

由于我对液体(和.html)不太熟悉,有人可以确认这足以达到我的目标吗?

以下是我将要处理的文件类型的示例:

<div class="post-preview">
    <div class="post-title">
        <div class="post-name">
            <a href="{{ post.url }}">{{ post.title }}</a>
        </div>
        <div class="post-date">
            {% include time.html %}
        </div>
    </div>

    <div class="post-snippet">
        {% if post.content contains '<!--break-->' %}
            {{ post.content | split:'<!--break-->' | first }}
            <div class="post-readmore">
                <a href="{{ post.url }}">read more-></a>
            </div>
        {% endif %}
    </div>
    {% include post-meta.html %}
</div>

在这种情况下我的正则表达式有效,但我想确保我不会遗漏未来的东西。我可以采用一种hackish方式,用

之类的评论来包围所有流动代码
/* start_liquid */ {blalala} /* end_liquid */

但我正在寻找一种更优雅的方式。

3 个答案:

答案 0 :(得分:1)

regular expression 中的 tokenizerPython-Liquid 对您的用例来说可能有点矫枉过正,但可以处理 {% comment %}{% raw %} 块以及任何多行标签。仅靠一个简单的正则表达式是无法应对的。

Python 的 re 文档中的 Writing a tokenizer 示例使用了相同的技术。

您可以使用 python-liquid 过滤掉像这样的 Liquid 代币。

from liquid.lex import get_lexer
from liquid.token import TOKEN_LITERAL

s = """
<div class="post-preview">
    <div class="post-title">
        <div class="post-name">
            <a href="{{ post.url }}">{{ post.title }}</a>
        </div>
        <div class="post-date">
            {% include time.html %}
        </div>
    </div>

    <div class="post-snippet">
        {% if post.content contains '<!--break-->' %}
            {{ post.content | split:'<!--break-->' | first }}
            <div class="post-readmore">
                <a href="{{ post.url }}">read more-></a>
            </div>
        {% endif %}
    </div>
    {% include post-meta.html %}
</div>
"""

tokenize = get_lexer()
tokens = tokenize(s)
only_html = [token.value for token in tokens if token.type == TOKEN_LITERAL]
print("".join(only_html))

注意输出保留了 Liquid 标记之外的换行符。

<div class="post-preview">
    <div class="post-title">
        <div class="post-name">
            <a href=""></a>
        </div>
        <div class="post-date">
            
        </div>
    </div>

    <div class="post-snippet">
        
            
            <div class="post-readmore">
                <a href="">read more-></a>
            </div>
        
    </div>
    
</div>

答案 1 :(得分:0)

说你应该但可以使用&#34;脏&#34;解决方案如:

{%\ (if)[\s\S]*?{%\ end\1\ %}|
{%.+?%}|
{{.+?}}

这与所提供的所有模板代码相匹配,请参阅a demo on regex101.com 额外的调整是扩展交替组(if)或完全使用解析器。

答案 2 :(得分:-2)

我实际上并不知道流动但我认为代码块总是包含在{}或{{}}中。我认为很难找到一个与这样的东西不匹配的正则表达式:

\{[^\}]*\}|\{\{[^\}]*\}\}

我建议您使用编辑器打开您的html文件,该编辑器会突出显示正则表达式的所有匹配项。例如,Kate或Geany就可以做到这一点。你可以半自动地用空字符串替换所有出现的事件。但是我强烈建议不要在不检查代码的情况下替换代码中的所有内容。你很可能会取代重要的东西。

我也会使用这个正则表达式:

SELECT userid
FROM LessonList
WHERE (LessonId = 102 and LessonValue IN (1002, 1008)) or
      (LessonId = 103 and LessonValue = 1003)
GROUP BY userid
HAVING COUNT(DISTINCT LessonId) = 2;

编辑(见上面的评论):

根据我的理解,我认为您希望有两种版本的代码可以使用液体或javascript。我想到的唯一优雅的解决方案是使用git来解决这个问题。您可以为项目创建两个单独的分支,一个用于液体,一个用于javascript。这允许您分别处理两个版本,并使您能够在两个版本之间切换。

编辑2:

我也不会放弃寻找更好的解决方案。您还可以重新发布您的问题,让其他用户更清楚您的问题。可能有更优雅的解决方案。