通过实例掌握流编辑器sed
缘由
由于Hugo对Markdown的解析和LaTeX存在诸多冲突。比如:当LaTex中出现\\
、\{
、\}
之类的东西,Hugo就无法正常解析数学公式。
解决方案之一就是用Hugo的shortcodes
机制,在md文件中用形如{{< katex [display] >}}latex code{{< /katex >}}
格式。
这样一来,网站显示正常了,但在本地Typora就无法识别了。 个人体验不好。
于是我想到用流编编器sed
对md内容进行替换。 我以前用sed
都是简单的情况,复杂需求我就不会用了。 于是有了此文。
需求
利用Hugo
发布到站点前:将$latex code$
,置换成 {{< katex [display] >}}latex code{{< /katex >}}
。
用Typora
写作编辑前: 将 {{< katex [display] >}}latex code{{< /katex >}}
,置换成 $latex code$
。
注意:置换时,同时要跳过代码块
不处理。
我写成的代码(后面将逐项解释,备忘)
#!/bin/bash
# md文件递归
function action(){
for file in `ls $1`
do
if [ -d $1"/"$file ]
then
action $1"/"$file
elif [ "${file#*.}"x = "md"x ]
then
# 方便发布到gitee
sed -i '/```/ { :begin1; /```.*```/! { $! { N; b begin1 }; }; n; }; /\$\$/ { :begin2; /\$\$[^$]*\$\$/! { $! { N; b begin2 }; }; }; s/\$\$\(\n[^$]*\n\)\$\$/{{< katex display >}}\1{{< \/katex >}}/g; s/\$\$\([^$]*\)\$\$/{{< katex >}}\1{{< \/katex >}}/g; s/!\[.*\](\.\.\/images\//![](..\/..\/images\//g;' $1"/"$file
fi
done
}
action ./content
if [ "$1"x = "server"x ]
then
# 站点本地预览
hugo server --disableFastRender -D
else
# 站点静态文件生成
hugo -D
# 文件恢复成Typora可正常阅读状态
./fortypora
fi
相关SED代码的详细解释(备忘)
把上面代码中SED部分单独提出来,写成方便阅读的形式,并逐行解释:
# 正则识别代码块的开始界定符
/```/ {
:begin1
# 正则识别完整代码块
/```.*```/! {
# 没能匹配代码块,则读取下行,附加到“模式空间”
$! { N; b begin1 }
}
# 成功匹配代码块,则读取下行,清空“模式空间”
n;
} # 上面这段代码目的: 跳过代码块```code```
# 正则识别标准数学公式开始界定符
/\$\$/ {
:begin2
# 正则识别完整的数学公式块(界定符)
/\$\$[^$]*\$\$/! {
# 没能数学公式块,则读取下行,附加到“模式空间”
$! { N; b begin2 }
}
}
# 对“(多行)模式空间” 进行置换:块公式的界定符变换
s/\$\$\(\n[^$]*\n\)\$\$/{{< katex display >}}\1{{< \/katex >}}/g
# 对“(多行)模式空间” 进行置换:内联公式的界定符变换
s/\$\$\([^$]*\)\$\$/{{< katex >}}\1{{< \/katex >}}/g
# 对“(多行)模式空间” 进行置换:顺带进行链接变换
s/!\[.*\](\.\.\/images\//![](..\/..\/images\//g
上面的注释已经解释的很清楚了:
- 展示了如何用SED进行多行匹配:先识别开始界定符,然后反复检查代码块的完整性,不完整则逐行添加,完整则继续。
- 这里只用到了"模式空间"。命令
N
可将”单行模式空间“扩展成”多行模式空间“;命令n
则将”多行模式空间“清空,恢复成”单行模式空间“。 - 最后通过
s/<正则匹配被替换老的部分>/<新的部分>/g
,完成置换。 - 注意: 把多行压缩时需要添加
;
(注意后面有个空格)。
一旦理解这个例子,我想一般的SED就不在话下。