前言
之前用python
从网络爬了一些引流文, 在使用hexo
渲染时出现大批量的报错, 如下:
1 | {% raw %} |
该错误是由于Nunjucks
模板引擎将文档中的双花括号{{}}
误解析为模板语法导致的冲突
解决方案也很简单, 那就是在双花括号前后添加raw
标签包裹, 如下:
1 | {% raw %}{{xxx}}{% endraw %} <!-- raw标签包裹 --> |
其目的是告诉Nunjucks
将花括号当做普通文本来显示
大批量替换
如果只是一两处修改还好, 问题是大量的文章存在这样的问题, 手动一一修改肯定不现实
要不写一个python
脚本自动替换一下?
可是可以, 没有办法的情况下只能这么干, 不过目前来说大可不必, 我们其实可以借助IDE的全局正则搜索替换功能, 比如vscode
具体操作
打开替换面板 快捷键
Ctrl+H (Windows/Linux)
或Cmd+Option+F (macOS)
启用正则表达式模式 (点击
.*
按钮或按Alt+R
)搜索框输入:
1
2
3
4
5{% raw %}
`(\{\{[^{}]*?\}\})`
或者
`(\{\{+.*?\}\}+)`
{% endraw %}[^{}]
确保只匹配非花括号字符*?
非贪婪匹配任意数量字符
替换框输入:
1
`{% raw %}$1{% endraw %}`
执行全部替换
优化点说明:
- 排除嵌套情况:
[^{}]
确保不会错误匹配{{a{b}c}}
这类嵌套结构 - 精确匹配:
*?
比.
更安全,避免过度匹配 - 保留原格式:
$1
会保持原变量的大小写和特殊字符
特殊场景处理:
- 若需包含换行符:改为
[\s\S]*?
- 若需排除特定前缀:使用
(?<!prefix)\{\{
常见语法冲突字符
除了双花括号之外, 还有类似的字符也需要进行替换, 不然hexo
渲染也会报错, 下面列举一些常见的需要去除或者替换的字符
hexo
标题不允许出现以下字符:
1 | : |
hexo
内容需要进行替换的字符:
1 | {% raw %} 这个忽略 |
对于{% xxx %}
的替换, 可以使用以下搜索正则表达式:
1 | \{%(?!(?:\s*raw\s|\s*endraw\s))([^%]+)%\} |
替换内容:
1 | {% raw %}{%$1%}{% endraw %} |
说明:
- 使用
(?:)
非捕获组同时排除raw
和endraw
标签 \s*
允许标签内可能存在的空格- 完整保留原始URL内容(通过$1引用)
其他报错问题
提示标签未闭合
1
2Template render error: (unknown path)
Error: expected end of comment, got end of file往往是因为出现了类似于
{#xxx}
的语法, 正确写法应该是{#xxx#}
如果数量比较多 可以使用正则搜索替换:
- 在搜索框中输入:
\]+)\}
- 在替换框中输入:``
- 在搜索框中输入:
如果碰上更复杂情况, 比如{#user,#user}
, 也是会报错的, 这时我们可以使用增强表达式:
1 | (?:^|(?<!\{% raw %\}))\{#([^#]*(?:#(?!\})[^#]*)*)\}(?!\s*\{% endraw %\}) |
替换成:
1 | {% raw %}{#$1}{% endraw %} |
提示
unexpected token
1
2
3
4{% raw %}
Nunjucks Error: [Line 94, Column 162] unexpected token:
94 | <p>要想保证双花括号初始化不会出现内存泄漏的办法也很简单,只需要被 <code>static</code> 修饰即可,但这样做还是存在潜在的风险,可能会被某人不小心删除掉,于是我们另寻它道,发现了可以使用 Java8 中的 Stream 或 Java9 中的集合工厂 <code>of</code> 方法替代"{{"。</p>
{% endraw %}问题处在未闭合的
{{
解决方案就是使用
raw
标签对花括号进行包裹如果数量比较多, 则依然使用正则全局替换, 在搜索框中输入以下正则表达式:
1
\{\{(?!(?:[^{}]*}}))
然后在替换框中输入:
1
{% raw %}{{{% endraw %}
表达式解释:
\{\{
- 匹配{{
字面量(转义特殊字符)(?!(?:[^{}]*}}))
- 负向先行断言,确保后面没有}}
闭合标签(?:[^{}]*}})
- 匹配任意非{}
字符后跟}}
?!
- 表示后面不能跟着这个模式
这个正则表达式只会匹配未闭合的
{{
标签,而不会匹配已闭合的{{...}}
标签。
总结
根据上面的探讨, 我们来做一个整合
按照以下步骤依次替换 能解决90%以上的问题, 剩下的手动改一下即可:
第一步 替换带引号的
{% xxx %}
1
`\{%(?!(?:\s*raw\s|\s*endraw\s))([^%]+)%\}`
替换:
1
`{% raw %}{#$1}{% endraw %}`
第二步 替换带引号
{{
和}}
搜索:
1
2
3`\{\{`
和
`\}\}`替换:
1
2
3`{% raw %}{{{% endraw %}`
和
`{% raw %}}}{% endraw %}`第三步 替换带引号
{{xxx}}
搜索:
1
`(\{\{+.*?\}\}+)`
替换:
1
`{% raw %}$1{% endraw %}`
第四步 替换
{#xxx}
搜索:
1
(?:^|(?<!\{% raw %\}))\{#([^#]*(?:#(?!\})[^#]*)*)\}(?!\s*\{% endraw %\})
替换:
1
{% raw %}{#$1}{% endraw %}
第五步 替换不带引号的
{{xxx}}
由于没有引号限制, 覆盖的范围会更广, 包括代码和注释
搜索:
1
(\{\{+.*?\}\}+)
替换:
1
{% raw %}$1{% endraw %}
第六步 替换不带引号
{% xxx %}
搜索:
1
\{%(?!(?:\s*raw\s|\s*endraw\s))([^%]+)%\}
替换:
1
{% raw %}{#$1}{% endraw %}
前三步可以放心大胆替换, 后面几步按需替换, 因为有些代码里面的花括号可以保留
补充
如果你想省事, 以牺牲文章部分内容和格式的前提下, 还有一种简单粗暴且有效的方法
那就是把整篇文章进行raw
标签包裹, 也就是文章开头加一个raw
标签, 文章结尾加一个endraw
标签
本文为作者原创 转载时请注明出处 谢谢