因为要发一些数学相关的文章,所以要用到Latex。后台的编辑器用的是一个markdown插件,处理代码,一些简单的排版都非常方便。但是因为要内嵌Latex公式,就会有一些转义字符的问题影响这些公式的编译。

比如说$\{a_n\}_{n=0}^{\infty} \in R$正确渲染的话应该是这样$\{a_n\}_{n=0}^{\infty} \in R$

但是因为markdown语法里_代表斜体,\是转义字符,所以直接写的话原本的Latex公式会变成file(注意第一个n和}是斜体),不会被正常编译。必须对原公式进行转义后,_\才会被留下。$\\{a\_n\\}\_{n=0}^{\\infty} \\in R$,这样的公式经过了markdown解析才会变成正确的公式。

不过如果手动一个个加\会非常的麻烦,一堆\看起来也很反人类。所以我稍微修改了一下原来的markdown插件,在markdown解析之前先对所有的Latex公式进行转义,这时候用正则表达式就特别的方便。

内嵌的Latex公式有两种语法,一种是$abc$,会编译成行内的公式,另外一种是$$abc$$,公式会占一整行。

对于第一种语法,可以用/\$[^\\\$]*(?:\\.[^\\\$]*)*\$/进行匹配。第二种语法的匹配也类似,只是用两个$符号/\$\$[^\\\$]*(?:\\.[^\\\$]*)*\$\$/

首先\$匹配到开始的$字符,然后[^\\\$]*匹配到任意多不是\或者$的字符。对于大部分的公式,到这里就已经匹配完毕了,最后的\$匹配结尾的$

剩下的这些主要是为了处理公式里的转义字符(转义再转义,确实很麻烦)。如果说想要输出$1\$\$23$,就得输入$1\$\$23$。最开始我写的正则表达式是/\$[\d\D]*?\$/,非常的简单,也确实可以用,开始和结尾匹配$,中间匹配任意字符(?表示非贪婪)。但是遇到带$转义字符的就不行了,$1\$\$23$会被匹配成$1\$$23$,并不是想要的结果。完整的正则表达式把\构成的转义字符单独处理,解决了这个问题。示例(这个网站里可以一步步看到正则表达式是如何匹配的)。

匹配成功后就是替换了,这个部分非常的简单,只要把所有的\换成\\_换成\_就可以了。

function preserve_latex($text)
{
    $text = preg_replace_callback('/\$[^\$\\\\]*(?:\\\\.[^\$\\\\]*)*\$/', function ($matches) {
        $slash = "\\";
        $dslash = "\\\\\\\\";
        $matches[0] = preg_replace("/\\\\/", $dslash, $matches[0]);
        $matches[0] = preg_replace("/_/", $slash . "_", $matches[0]);
        return $matches[0];
    }, $text);
    $text = preg_replace_callback('/\$\$[^\$\\\\]*(?:\\\\.[^\$\\\\]*)*\$\$/', function ($matches) {
        $slash = "\\";
        $dslash = "\\\\\\\\";
        $matches[0] = preg_replace("/\\\\/", $dslash, $matches[0]);
        $matches[0] = preg_replace("/_/", $slash . "_", $matches[0]);
return $matches[0]; }, $text); return $text; }

这一段是匹配和替换的php代码,可以做一个参考。正则表达式作为字符串又要经过一边转义,要表示\\甚至得输入'\\\\\\\\'

发表评论

邮箱地址不会被公开。 必填项已用*标注