.Net 正则表达式匹配 $ 与字符串的结尾而不是行的结尾,即使启用了多行

Posted

技术标签:

【中文标题】.Net 正则表达式匹配 $ 与字符串的结尾而不是行的结尾,即使启用了多行【英文标题】:.Net regex matching $ with the end of the string and not of line, even with multiline enabled 【发布时间】:2017-02-24 18:39:19 【问题描述】:

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

以下表达式:^(#+).+$ 适用于任何在线正则表达式测试工具:

但它拒绝使用 .net:

它似乎没有考虑 $ 标记,并且只是突出显示直到字符串末尾的所有内容,无论如何。这是我的 C#

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

我错过了什么?

【问题讨论】:

点不能匹配没有 DOTALL 修饰符的 LF。你能分享一个dotnetfile吗? 你有一个 CR 结尾。使用@"^(#+).+?\r?$" 【参考方案1】:

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

Multiline Mode MSDN regex reference

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

所以,使用

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

.+?\r?$ 将延迟匹配除 LF 之外的任何一个或多个字符,直到换行符之前的第一个 CR(这是可选的)。

或者只使用否定字符类:

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

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

【讨论】:

不幸的是,当我使用 Regex.Replacec 时,它会替换 \r 字符((我可以修复它吗? @Deni35 好像有新问题,请教 可以用这种模式匹配行尾:(?=\r?$)【参考方案2】:

你所拥有的是好的。您唯一缺少的是 . 不匹配换行符,即使使用多行选项也是如此。您可以通过两种不同的方式解决此问题。

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

解决此问题的另一种方法(尽管我不会为您的用例推荐它)是修改您的正则表达式以明确允许换行符。为此,您可以将任何. 替换为(?:.|\n),这意味着任何字符或换行符。对于您的示例,您最终会得到^(#+)(?:.|\n)+$。如果要确保首先有一个非换行符,请添加一个额外的点:^(#+).(?:.|\n)+$

【讨论】:

我想你误解了我的问题。我不想匹配新行。第二张图是我得到的,第一张图是我应该得到的。输入字符串“this is a \n #header \n but this is not”应该只匹配“#header”。目前,它匹配“#header but this is not” 请不要建议(?:.|\n)+ 模式。它的效率非常低,并且可能由于它必须执行的回溯(或在惰性量词的情况下扩展)步骤的数量而导致系统冻结。在 .NET 中始终使用 .(?s) 内联修饰符或 RegexOptions.Singleline。您不需要每次都使用 [\s\S] 之类的解决方法,因为您可以在 .NET 正则表达式中使用修饰符组。例如:^.*\r?\n(?s:.*).

以上是关于.Net 正则表达式匹配 $ 与字符串的结尾而不是行的结尾,即使启用了多行的主要内容,如果未能解决你的问题,请参考以下文章

正则前面的 (?i) (?s) (?m) (?is) (?im)

正则匹配开头为''结尾为','应该怎么写?

我需要一个正则表达式结果,不包括匹配模式的开头和结尾的子字符串

正则表达式匹配不是特定子字符串的内容

oracle正则表达式问题。有个字符串abca4gf,我想匹配a开头,f结尾的字符串, 我想要的结

字符串的正则表达式不以给定的后缀结尾