前言
之前用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 
 2- Template 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标签
本文为作者原创 转载时请注明出处 谢谢
