对于这类问题,Lookbehind 是每个人首先想到的,但它是错误的工具,即使在 .NET 这样支持不受限制的lookbehinds 的风格中也是如此。你可以破解一些东西,但它会很丑陋,即使在 .NET 中也是如此。这是一个更好的方法:
`[^`\\]*(\\.[^`\\]*)*`
第一部分从开始的分隔符开始,吞噬任何不是分隔符或反斜杠的东西。如果下一个字符是反斜杠,它会使用该反斜杠及其后面的字符,无论它可能是什么。它可以是分隔符、另一个反斜杠或其他任何东西,没关系。
它会根据需要多次重复这些步骤,当两者[^`\\]
都不\\.
匹配时,下一个字符必须是结束分隔符。或字符串的结尾,但我假设输入格式正确。但如果格式不正确,这个正则表达式将很快失败。我提到由于这种其他方法,我看到了很多:
`(?:[^`\\]+|\\.)*`
这适用于格式正确的输入,但是如果您从示例输入中删除最后一个反引号会发生什么?
"hello `how\` are you"
根据 RegexBuddy 的说法,在遇到第一个反引号后,该正则表达式执行了 9,252 次不同的操作(或步骤),然后才可以放弃并报告失败;我的十步失败了。
编辑要仅提取分隔符内的 par,将该部分包装在捕获组中。您仍然必须手动删除反斜杠。
`([^`\\]*(?:\\.[^`\\]*)*)`
我还将另一组更改为非捕获,我应该从一开始就这样做。我不会避免虔诚地捕获,但是如果您使用它们来捕获东西,那么您使用的任何其他组都应该是非捕获的。
编辑我认为我对这个问题的了解太多了。在 StackOverflow 上,如果您想在内联代码段或注释中包含文字反引号,您可以使用三个反引号作为分隔符,而不仅仅是一个。由于不需要转义反引号,因此您也可以忽略反斜杠。您的正则表达式可能会像这样简单:
```(.*?)```
处理错误分隔符的可能性,您使用相同的基本技术:
```([^`]*(?:`(?!``)[^`]*)*)```
这就是你所追求的吗?
顺便说一句,这个答案与@nneonneo 上面的评论并不矛盾。这个答案没有考虑比赛发生的环境。它在程序或网页的源代码中吗?如果是,匹配是否出现在注释或字符串文字中?我怎么知道我发现的第一个反引号没有逃脱?正则表达式对它们运行的上下文一无所知。这就是解析器的用途。