.Net 正则表达式处理中“$”限定符的潜在不当行为 [重复]

Posted

技术标签:

【中文标题】.Net 正则表达式处理中“$”限定符的潜在不当行为 [重复]【英文标题】:Potential misbehavior of the "$" qualifier in the .Net Regular Expression processing [duplicate] 【发布时间】:2018-10-22 12:41:30 【问题描述】:

The documentation 说:

限定符$

说明:匹配必须出现在字符串的末尾或行或字符串末尾的\n之前。

模式示例-\d3$

文本匹配示例-333 in -901-333

我预计当我们使用RegexOptions.Singleline 时,限定符$ 将匹配字符串结尾,当我们使用RegexOptions.Multiline 时匹配行尾,如下所示:

using System;
using System.Text.RegularExpressions;
namespace ConsoleApp2

    class Program
    
        static void Main(string[] args)
        
            var text = @"_
abc
123
do-re-me";
            var pat = @"\w+$";
            var re = new Regex(pat, RegexOptions.Multiline);
            var ms = re.Matches(text);
            var i = 0;
            foreach (Match m in ms)
                Console.WriteLine($"i++.  m");
            Console.ReadKey();
        
    

上面的代码(RegexOptions.Multiline)导致:

0.  me

我将 .Net framework 4.7.1 和 .Net Core 2.0 与控制台应用程序一起使用,得到了相同的结果。

我预计结果是:

0.  _
1.  abc
2.  123
3.  me

请注意,^ 限定符按预期工作。使用RegexOptions.Multiline 时匹配行首,使用RegexOptions.Singleline 时匹配字符串开头。

谁能解释$ 限定符的行为?

【问题讨论】:

【参考方案1】:

我预测您正在 Windows 机器上编写此源代码...其中行尾 - 嵌入在逐字字符串文字中 - 是“\r\n”,而不是“\n”。

您当前正在查找后跟“\n”的单词字符 - 它不会找到,因为中间有一个“\r”。

如果您先删除“\r”字符,它会按预期工作:

text = text.Replace("\r", "");

或者,只需将源代码的格式更改为使用“\n”而不是“\r\n”作为行尾。或者作为第三种选择,不要使用逐字字符串文字:

string text = "_\nabc\n123\ndo-re-me";

这些选项中的任何一个都会给您预期的结果。

不幸的是,这是逐字字符串文字的问题之一。如果您使用的源代码控制系统在克隆时会自动在格式之间进行转换,则问题尤其严重:(

【讨论】:

【参考方案2】:

另一个答案阐明了这个问题,但您不需要从字符串中删除回车符。它已在documentation 中清除。您想使用 \r?$ 而不是单独使用 $

如果你使用 $RegexOptions.Multiline 选项,匹配可以 也出现在一行的末尾。请注意 $ 匹配 \n 但不 匹配\r\n(回车和换行符的组合, 或 CR/LF)。要匹配 CR/LF 字符组合,请在其中包含 \r?$ 正则表达式模式。

【讨论】:

以上是关于.Net 正则表达式处理中“$”限定符的潜在不当行为 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

PHP 正则表达式

python正则表达式管道符的使用?

使用正则表达式(.net 和 C#)识别行尾

正则表达式简要

Linux:正则表达式及:grep工具

SSIS 处理缺少文本限定符的平面文件