使用正则表达式转义代码块内的标记

Escaping markup inside code blocks using regex

我目前正在尝试在我的 Web 应用程序中实现我自己对 Discord 降价风格的看法。 我这样做的方法只是通过链接替换方法,每次检查并用适当的 HTML 标记替换语法(我会清理,别担心)。

let description = description.replace(/\`{3}([\S\s]*?)\`{3}/g, '<code></code>')
      .replace(/\`(.*)\`/g, '<code class="inline"></code>')
      .replace(/~~([\S\s]*?)~~/g, '<s></s>')

我面临的问题是正则表达式也匹配整个代码块内部以及内联代码。这种行为是不希望的。

**bold and 
*italic and 
__underline and 
~~strikethrough~~__***

`~~Not strikethrough~~`
~~`Strikethrough`~~

Normal text

```
~~Not strikethrough~~
```

~~```
Strikethrough
```~~

**bold and 
*italic and 
__underline and 
~~strikethrough~~__***

`~~Not strikethrough~~`
~~`Strikethrough`~~

Normal text

我试过这样的事情:/(?<!`[\S\s])\*([\S\s]*?)\*(?!`)/g 但我无法让它像预期的那样工作。

我仍在学习正则表达式,并且仍然发现很难全神贯注,因此非常感谢任何和所有帮助。

一月。 4. 2021 对不起,我之前没有澄清,但样式应该是“可嵌套的”,或者换句话说可以组合,例如***strong and italic*** 应该变成 strong and italic

我更新了输入文本(见上文)以更好地封装所有可能的用例。

您可以使用

let text = "**bold and \n*italic and \n__underline and \n~~strikethrough~~__***\n\n`~~Not strikethrough~~`\n~~`Strikethrough`~~\n\nNormal text\n\n```\n~~Not strikethrough~~\n```\n\n~~```\nStrikethrough\n```~~\n\n**bold and \n*italic and \n__underline and \n~~strikethrough~~__***\n\n`~~Not strikethrough~~`\n~~`Strikethrough`~~\n\nNormal text";
const re = /<code(?:\s[^>]*)?>[\s\S]*?<\/code>|`{3}([\S\s]*?)`{3}|`([^`]*)`|~~([\S\s]*?)~~|\*{2}([\s\S]*?)\*{2}(?!\*)|\*([^*]*)\*|__([\s\S]*?)__/g;
let tmp="";
do {
  tmp = text;
  text = text.replace(re, (match, a, b, c, d, e, f) => f ? `<u>${f}</u>` : e ?  `<i>${e}</i>` : d ? `<b>${d}</b>` : c ? `<s>${c}</s>` : b ? `<code class="inline">${b}</code>` : a ? `<code>${a}</code>` : match);
}
while (text != tmp);
console.log(text);

参见regex demo

重点是为单次传递设计一个正则表达式,并将字符串部分捕获到单独的组中以应用不同的替换逻辑。

有3个选项匹配

  • `{3}([\S\s]*?)`{3} - 三重星号之间的任何子字符串将其捕获到组 1 (x)
  • `([^`]*)` - 单个星号之间的任何子字符串将其捕获到第 2 组 (y)
  • ~~([\S\s]*?)~~ - ~~ 之间的任何子字符串将其捕获到第 3 组 (z)

参见regex demo