.NET Regex Negative Lookahead - what am I doing wr

2019-03-03 18:58发布

Assuming I have:

StartTest
  NoInclude
EndTest

StartTest
  Include
EndTest

and am using:

/StartTest(?!NoInclude)[\s\S]*?EndTest/g

Why am I matching both groups?

Regexr example: http://regexr.com/3db8m

1条回答
兄弟一词,经得起流年.
2楼-- · 2019-03-03 19:46

You fail the match with the lookahead if NoInclude appears straight after StartTest. You need a tempered greedy token:

(?s)StartTest(?:(?!(?:Start|End)Test|NoInclude).)*EndTest
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

See the regex demo

The regex is matching StartTest, then matches any text that is not StartTest, EndTest or NoInclude, up to the EndTest.

Since the * is greedy, it will make the . match as much as it can. The negative lookahead will make it stop matching at the locations that are followed with the following alternatives:

  • (?:Start|End)Test - StartTest or EndTest
  • NoInclude - just NoInclude.

NOTE: The (?s) is an inline modifier (equivalent of RegexOptions.Singleline flag) that modifies the . behavior in a pattern making it match LF (newlines), too. Without this modifier (or without RegexOptions.Singleline) a dot matches any character but a newline.

NOTE2: If you are testing a regex outside of the native code environment, make sure you are using an appropriate tester for your regex flavor. regexr.com only supports JavaScript flavor, regex101.com supports JS, PCRE and Python flavors, and RegexStorm.net/RegexHero.net support .NET flavor. There are many more testers around, read what they support and what not first.

Here is a C# demo:

using System;
using System.IO;
using System.Text.RegularExpressions;
using System.Linq;
public class Test
{
    public static void Main()
    {
        var input = "StartTest\n  NoInclude\nEndTest\n\nStartTest\n  Include\nEndTest";
        var regex = new Regex(@"(?s)StartTest(?:(?!(?:Start|End)Test|NoInclude).)*EndTest");
        var results = regex.Matches(input).Cast<Match>()
                       .Select(p => p.Value)
                       .ToList();
        Console.WriteLine(string.Join("\n", results));
    }
}
查看更多
登录 后发表回答