正则美化 Markdown(单词前后加上$)

534 阅读4分钟

背景

昨天在刷力扣,刷完之后写了一篇题解。就在我将 VSCodeVSCode 上面的题解粘贴到力扣上面时,发现渲染出来的样式惨不忍睹,特别是英文单词的样式。

VSCodeVSCode 上面的题解:

力扣上面的题解:

上面的样式看起来非常不舒服,格式混乱。左边是 MarkdownMarkdown 文档的源代码,右边是渲染出来的样子。了解 MarkdownMarkdown 格式的同学一眼就能看出来,每一行前面的点是由 * 渲染出来的,在单词前后加上一个 $ 会使单词的样式更好看,在行内代码前后加上一个 ` 会让行内代码样式更美观。

解决方案

要让渲染出来的文档变得美观,需要手动调整一下:

  • 删除多余的 *,将每一行前面的 * 删除,但是不能删除表达式中的乘号
  • 为每一句行内代码前后加上 `
  • 为每一个单词前后加上 $

纯手工的方法适用于篇幅较小的文章,而且一不小心就可能漏掉某个单词或者某句行内代码。作为一名喜欢捣鼓的技术小白,自然是能偷懒就偷懒,这种重复性的无意义的工作,还是交给正则来做吧。我要做的就是写一个正则表达式,替换 MarkdownMarkdown 源代码中的内容,让页面更美观。

一般的 MarkdownMarkdown 文档或者编译器都有 查找和替换 的功能,可能有些人不知道,它是可以匹配正则表达式的。

上面 \s\w\s 中的 ss 代表 spacespace,表示匹配空格;ww 代表 wordword,表示匹配单词,所以可以匹配所有的前后有空格的单词。正则的基础语法不会还有同学不会吧 QWQ。

我们就利用这里的查找和替换的功能,来做格式的美化。

删除多余 *

这个很简单,只需要匹配每行开头的 *,并删除它就行了,因为正常的乘号是不会出现在一行的开头的,乘号的前后肯定有变量或者数字。使用这个正则表达式进行匹配:^\s*\s*

其中 ^ 表示匹配开始位置,紧接着 \s 匹配空格,再接着 \* 匹配 *,这里的 * 需要转义,因为在正则中,* 表示 00 个或者多个字符,需要加上转义符,才能匹配真正的 *。然后再用 \s* 匹配末尾的 00 个或者多个空格。

加上 ^ 之后,就不会匹配正常的乘号了。

然后替换的内容为空,这样就可以一键将每一行前面的 * 删除了。

行内代码前后加上 `

这个有点难办了,首先何谓行内代码?有加减乘除、有等于、有中括号等就算是行内代码吗?这个得看个人的定义了。这里我是在所有非中文、非标点字符串前后加上了 `。大佬们有更好的办法望不吝赐教 QWQ。

上面中括号中的 ^ 表示非的意思,\u4e00-\u9fa5 表示匹配中文字符,后面例举了一些中文标点,如果不够的话可以自己加。用中括号括起来的意思就是:匹配中括号中的任意一个。在中括号中最前面加上 ^ 表示:匹配除了中括号中字符之外的字符。所以它能匹配所有非中文、非标点字符。

注意:最后需要加上 +,表示匹配一个或者多个非中文、非标点字符。此时正则会使用贪婪模式,匹配最长的非中文、非标点字符串。

如果不加 +,正则只会匹配一个非中文、非标点字符;如果在 + 后面加上 ?,正则会使用非贪婪模式,也只会匹配一个非中文、非标点字符。这个时候去一键替换,会在每一个非中文、非标点字符前后都加上 `

再之后,需要手动修改一下没匹配到的地方,或者匹配错误的地方。没有通用的正则表达式,只能先这么干了 QWQ。

单词前后加上 $

在这里,我的匹配规则很简单,因为我习惯在单词和中文之间写空格,所以可以这样匹配:\s(\w)\s。虽然不太完美,但是暂时先这么做吧 QWQ。\s 表示匹配空白符,\w 表示匹配单词。\w 外边加上括号是为了提取出 \w 匹配的单词,方便后面替换使用。

匹配规则写好了,替换规则呢?是 $$1$ 这样的吗?

我们知道,在正则中 $ 有不同的含义,$1 表示匹配到的第一个括号里面的内容,然后在 $1 前后分别加上一个 $,这样就能将匹配到的单词替换为前后加了 $ 的单词。可是替换之后,却发现所有匹配到的单词全都变成了 $1$,而我想要它变成原来的单词前后加上一个 $

为什么会这样呢?很明显 $ 有特殊的含义,不能在 $1 前后直接加上 $。那我将 $ 转义之后再加上呢?\$$1\$ 这样可以吗?很遗憾,还是不行。

它直接在单词前后加上了 \$。转义也不行,不转义也不行。难道正则里面就没有能表示真正 $ 符号的方式吗?

经过一番搜索,找到了答案,在正则的替换规则中,使用 $$ 来表示真正的 $ 符号,替换“$”字符这篇文章可以找到答案。替换之后是这样:

渲染出来是这样:

好像少了空格,再改一下,把空白符也原封不动地拿过来:

匹配规则 $1$$$2$$$3 中,$1 表示第一个括号中匹配到的内容,也就是单词前面的空白符;紧接着 $$ 表示渲染为 $;然后 $2 表示第二个括号中匹配到的内容,也就是匹配到的单词;再之后的 $$ 也表示渲染为 $;最后的 $3 表示第三个括号中匹配到的内容,也就是单词后面的空白符。

这样就可以了,再之后就需要处理一下没有被替换的单词,或者替换错误的单词。

参考文章