正则表达式包括结果中应该是非捕获组的内容

myu*_*srn 2 .net c# regex

我有以下简单的测试,我试图获取 Regex 模式,以便它在没有“.exe”后缀的情况下猛拉可执行文件名称。
 
看来我的非捕获组设置(?:\\.exe)不起作用,或者我误解了它的工作原理。
 
无论regex101regexstorm.net显示了同样的结果和前确认“(?:\。exe文件)”是一个非获取匹配。
 
关于我做错了什么的任何想法?

// test variable for what i would otherwise acquire from Environment.CommandLine
var testEcl = "\"D:\\src\\repos\\myprj\\bin\\Debug\\MyApp.exe\" /?"
var asmName = Regex.Match(testEcl, @"[^\\]+(?:\.exe)", RegexOptions.IgnoreCase).Value;
// expecting "MyApp" but I get "MyApp.exe"
Run Code Online (Sandbox Code Playgroud)

我已经能够通过使用定义了组名的匹配模式来提取我想要的值,如下所示,但想了解为什么非捕获组设置方法没有按我预期的方式工作。

// test variable for what i would otherwise acquire from Environment.CommandLine
var testEcl = "\"D:\\src\\repos\\myprj\\bin\\Debug\\MyApp.exe\" /?"
var asmName = Regex.Match(Environment.CommandLine, @"(?<fname>[^\\]+)(?<ext>\.exe)", 
    RegexOptions.IgnoreCase).Groups["fname"].Value;
// get the desired "MyApp" result
Run Code Online (Sandbox Code Playgroud)

/eoq

Wik*_*żew 6

一个(?:...)是一个非捕获组比赛,仍然会消耗文本。这意味着该组匹配的文本部分仍会添加到整体匹配值中。

一般来说,如果你想匹配一些东西而不是消费,你需要使用lookarounds。因此,如果您需要匹配特定字符串后跟的内容,请使用正向前瞻(?=...)构造:

some_pattern(?=specific string) // if specific string comes immmediately after pattern
some_pattern(?=.*specific string) // if specific string comes anywhere after pattern
Run Code Online (Sandbox Code Playgroud)

如果您之前需要匹配但“从匹配中排除”某些特定文本,请使用积极的lookbehind

(?<=specific string)some_pattern // if specific string comes immmediately before pattern
(?<=specific string.*?)some_pattern // if specific string comes anywhere before pattern
Run Code Online (Sandbox Code Playgroud)

注意,.*?或者.*-也就是说,用图案*+?{2,}甚至{1,3}量词-在回顾后发模式并不总是由正则表达式引擎的支持,然而,C#.NET正则表达式引擎幸运支持它们。它们还得到 Python PyPiregex模块、Vim、JGSoft 软件以及现在符合 ECMAScript 2018 的 JavaScript 环境的支持。

在这种情况下,您可能会捕获您需要获取的内容,而无需捕获即可匹配上下文:

var testEcl = "\"D:\\src\\repos\\myprj\\bin\\Debug\\MyApp.exe\" /?";
var asmName = string.Empty; 
var m = Regex.Match(testEcl, @"([^\\]+)\.exe", RegexOptions.IgnoreCase);
if (m.Success)
{
    asmName = m.Groups[1].Value;
}
Console.WriteLine(asmName);
Run Code Online (Sandbox Code Playgroud)

参见C# 演示

细节

  • ([^\\]+)-捕获组 1:一个或多个字符,而不是\
  • \. - 一个文字点
  • exe- 文字exe子串。

因为我们只对捕获组 #1 的内容感兴趣,所以我们抓取m.Groups[1].Value,而不是整个m.Value(包含.exe)。