使用.NET正则表达式匹配字符串末尾而不是行的末尾,即使启用了多行模式。

10

我正在尝试突出显示markdown代码,但遇到了.NET正则表达式多行选项的奇怪行为。

以下表达式:^(#+).+$ 在任何在线正则表达式测试工具上都可以正常工作:

enter image description here

但是它拒绝在.net中使用:

enter image description here

它似乎没有考虑到$标记,并且只高亮显示整个字符串直到结尾,无论如何。这是我的C#:

RegExpression = new Regex(@"^(#+).+$", RegexOptions.Multiline)

我漏掉了什么?

一个点不能匹配LF,除非使用DOTALL修饰符。你能分享一个dotnetfidle吗? - Wiktor Stribiżew
你有一个CR结尾。请使用@"^(#+).+?\r?$" - Wiktor Stribiżew
2个回答

10

很明显您的文本包含除LF以外的换行符。在.NET正则表达式中,点匹配除LF(一个换行符,\n)以外的任何字符。

请参见多行模式 MSDN 正则表达式参考

  

默认情况下,$仅匹配输入字符串的结尾。如果指定了RegexOptions.Multiline选项,则它将匹配换行符(\n)或输入字符串的结尾。但是,它不匹配回车符/换行符组合。要成功匹配它们,请使用子表达式\r?$而不是只使用$

因此,请使用

@"^(#+).+?\r?$"

.+?\r?$将懒惰地匹配除LF以外的一个或多个字符,直到第一个换行符(可选)之前的CR。

或者只需使用否定字符类:

@"^(#+)[^\r\n]+"

[^\r\n]+ 匹配除 CR/LF 之外的一个或多个字符。


1
很不幸,当我使用 Regex.Replacec 时,它会替换掉 \r 字符。我该怎么解决? - Denis535
@Deni35 看起来你有一个新问题,请提问。 - Wiktor Stribiżew
可以使用以下模式匹配行尾:(?=\r?$) - Denis535

0

你的代码已经很不错了。唯一缺少的是,即使使用多行选项,. 也无法匹配换行符。你可以通过两种不同的方式解决这个问题。

最简单的方法是使用 RegexOptions.Singleline 标志,它会将换行符视为字符。这样,^ 仍然匹配字符串的开头,$ 匹配字符串的结尾,. 匹配包括换行符在内的所有内容。

另一种修复此问题的方法(虽然我不建议你在这种情况下使用)是修改你的正则表达式以明确允许换行符。你只需将任何 . 替换为 (?:.|\n),表示任何字符或换行符。对于你的示例,你最终会得到 ^(#+)(?:.|\n)+$。如果你想确保首先有一个非换行符字符,请添加一个额外的点:^(#+).(?:.|\n)+$


我觉得你误解了我的问题。我不想匹配换行符。第二张图片是我得到的结果,而第一张图片是我应该得到的结果。输入字符串“this is a \n #header \n but this isn't”只应该匹配“#header”。目前,它正在匹配“#header but this isn't”。 - user2950509
1
请勿建议使用 (?:.|\n)+ 模式。它非常低效,可能会因为需要执行大量回溯(或懒惰限定符情况下的扩展),导致系统冻结。在 .NET 中,请始终使用带有 (?s) 内联修饰符或 RegexOptions.Singleline.。您无需像工作区中使用 [\s\S] 一样的解决方法,因为您可以在 .NET 正则表达式中使用修改器组。例如: ^.*\r?\n(?s:.*) - Wiktor Stribiżew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接