Regex前瞻赢得';不能在.NET中工作

本文关键字:不能 NET 工作 Regex | 更新日期: 2023-09-27 18:21:09

我得到了一个带有前瞻性的Regex,它可以与Regexr.com一起使用,但在.NET应用程序中使用时却不能。

这是一些示例输入数据(请注意,我只是为了可读性而创建了换行符,文本实际上只是一长行,因此需要正则表达式)。

26. AUG'r'n2014'r'n27.08 Testing 1'r'n -100'r'n
20. AUG'r'n2014'r'n27.08 Testing 2'r'n -90'r'n
15. AUG'r'n2014'r'n27.08 Testing 3'r'n 200'r'n
9. AUG'r'n2014'r'n27.08 Testing 4'r'n 50'r'n
4. AUG'r'n2014'r'n27.08 Testing 5'r'n -200'r'n
25. JUL'r'n2014'r'n27.08 Testing 5'r'n -200'r'n

使用以下正则表达式:

(.+?)(?=(''r''n'd{1,2}[.] [A-Z]{3})|$)

,我希望捕捉每一行,并希望用"20"来分隔它们。AUG"等等。由于分隔符也应该被捕获,所以我使用前瞻。Regexr.com上的一切都很好,例如:http://regexr.com/39fd7

在.NET:中执行此操作时

Regex.Matches(input, "(.+?)(?=('r'n''d{1,2}[.] [A-Z]{3})|$)")

我只得到这些结果:

-100
-90
200
50
-200
-200

我尝试过各种RegexOptions,比如multiline和其他一些,但没有结果。

如有任何帮助或提示,我们将不胜感激。感谢

Regex前瞻赢得';不能在.NET中工作

编辑

根据这些评论,原来的问题显然具有误导性。问题源于以下方面:

原始的C#代码使用一个字符串文字,其中包含确切的字符序列'r'n,例如:

string input = "Example'r'nText";

然后,字符串的内容被复制到在线正则表达式测试仪中,保持不变,因此测试在以下等价物上运行:

string notActuallyTheInput = "Example''r''nText"; 

现在很清楚,这个问题意味着input字符串文字写在一行上,但输入本身确实跨越了多行。因此,问题出在表达式的(.+?)部分。正如Robin所提到的,默认情况下.字符与换行符不匹配。所需的行为是RegexOptions.Singleline选项的行为,如下面的示例程序所示。

using System;
using System.Text.RegularExpressions;
class Program
{
    private const string Input =
        "26. AUG'r'n2014'r'n27.08 Testing 1'r'n -100'r'n" +
        "20. AUG'r'n2014'r'n27.08 Testing 2'r'n -90'r'n" +
        "15. AUG'r'n2014'r'n27.08 Testing 3'r'n 200'r'n" +
        "9. AUG'r'n2014'r'n27.08 Testing 4'r'n 50'r'n" +
        "4. AUG'r'n2014'r'n27.08 Testing 5'r'n -200'r'n" +
        "25. JUL'r'n2014'r'n27.08 Testing 5'r'n -200'r'n";
    static void Main(string[] args)
    {
        string pattern = @"(.+?)(?=('r'n'd{1,2}[.] [A-Z]{3})|$)";
        var matches = Regex.Matches(Input, pattern, RegexOptions.Singleline);
        Console.WriteLine("{0} Matches:", matches.Count);
        foreach (Match match in matches)
            Console.WriteLine("  {0}", match.Value.Replace("'r", "''r").Replace("'n", "''n"));
        // OUTPUT:
        //
        // 7 Matches:
        //   26. AUG'r'n2014'r'n27.08 Testing 1'r'n -100
        //   'r'n20. AUG'r'n2014'r'n27.08 Testing 2'r'n -90
        //   'r'n15. AUG'r'n2014'r'n27.08 Testing 3'r'n 200
        //   'r'n9. AUG'r'n2014'r'n27.08 Testing 4'r'n 50
        //   'r'n4. AUG'r'n2014'r'n27.08 Testing 5'r'n -200
        //   'r'n25. JUL'r'n2014'r'n27.08 Testing 5'r'n -200'r
        //   'n
    }
}

原始答案

这个问题可能源于正则表达式到C#字符串文本的错误翻译。

以下表达式:

(.+?)(?=(''r''n'd{1,2}[.] [A-Z]{3})|$)

将在C#字符串文字中写成以下任意一个:

"(.+?)(?=(''''r''''n''d{1,2}[.] [A-Z]{3})|$)"
@"(.+?)(?=(''r''n'd{1,2}[.] [A-Z]{3})|$)"

由于输入不包含任何引号字符,后者肯定是最简单的翻译,因为它是原始表达式的精确副本。

复制结果的完整程序

using System;
using System.Text.RegularExpressions;
class Program
{
    private const string Input =
        "26. AUG''r''n2014''r''n27.08 Testing 1''r''n -100''r''n" +
        "20. AUG''r''n2014''r''n27.08 Testing 2''r''n -90''r''n" +
        "15. AUG''r''n2014''r''n27.08 Testing 3''r''n 200''r''n" +
        "9. AUG''r''n2014''r''n27.08 Testing 4''r''n 50''r''n" +
        "4. AUG''r''n2014''r''n27.08 Testing 5''r''n -200''r''n" +
        "25. JUL''r''n2014''r''n27.08 Testing 5''r''n -200''r''n";
    static void Main(string[] args)
    {
        string pattern = @"(.+?)(?=(''r''n'd{1,2}[.] [A-Z]{3})|$)";
        var matches = Regex.Matches(Input, pattern);
        Console.WriteLine("{0} Matches:", matches.Count);
        foreach (Match match in matches)
            Console.WriteLine("  {0}", match.Value);
        // OUTPUT:
        //
        // 6 Matches:
        //   26. AUG'r'n2014'r'n27.08 Testing 1'r'n -100
        //   'r'n20. AUG'r'n2014'r'n27.08 Testing 2'r'n -90
        //   'r'n15. AUG'r'n2014'r'n27.08 Testing 3'r'n 200
        //   'r'n9. AUG'r'n2014'r'n27.08 Testing 4'r'n 50
        //   'r'n4. AUG'r'n2014'r'n27.08 Testing 5'r'n -200
        //   'r'n25. JUL'r'n2014'r'n27.08 Testing 5'r'n -200'r'n
    }
}

如果您的文本始终具有相同的格式(由4列,由文字'r'n分隔),则可以使用以下简单模式:

string pattern = @"(?:[^'']+''r''n){4}";

示例

默认情况下,正则表达式通配符.与换行符不匹配。

您的字符串显示为"一行",但包含换行符('r'n),一旦在字符串文字中进行解释,就会阻止点与您想要的所有内容匹配。

它将尝试匹配26. AUG,然后匹配2014。。。直到-100,当前景最终匹配时,即您的最终结果。

使用点匹配所有标志:

(?s).+?(?=''r''n'd{1,2}[.] [A-Z]{3}|$)