我有以下简单测试,我试图获取 Regex 模式,以便它提取没有“.exe”后缀的可执行文件名称。
我的非捕获组设置 (?:\\.exe) 似乎不起作用,或者我误解了它的工作原理。
两者 regex101和 regexstorm.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"
我已经能够通过使用定义了组名的匹配模式来提取我想要的值,如下所示,但我想了解为什么非捕获组设置方法没有按我预期的方式工作到。
// 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
/欧克
请您参考如下方法:
(?:...) 是一个非捕获组,它匹配并仍然使用 文本。这意味着该组匹配的文本部分仍将添加到整体匹配值中。
一般,如果你想匹配某样东西而不消费,你需要使用lookarounds。因此,如果您需要匹配后跟特定字符串的内容,请使用正向先行、(?=...) 构造:
some_pattern(?=specific string) // if specific string comes immmediately after pattern
some_pattern(?=.*specific string) // if specific string comes anywhere after pattern
如果您之前需要匹配但“从匹配中排除”某些特定文本,请使用正面回顾:
(?<=specific string)some_pattern // if specific string comes immmediately before pattern
(?<=specific string.*?)some_pattern // if specific string comes anywhere before pattern
请注意 .*? 或 .* - 即带有 *、+、?、{2,} 甚至 {1,3} 量词 - 在后视模式中,正则表达式引擎并不总是支持,但是,C# . NET 正则表达式引擎幸运地支持它们。它们还受到 Python PyPi regex 模块、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);
参见 C# demo
详情
([^\\]+)- 捕获第 1 组:\ 以外的一个或多个字符
\.- 文字点exe- 文字exe子字符串。
因为我们只对捕获组 #1 的内容感兴趣,所以我们捕获 m.Groups[1].Value,而不是整个 m.Value(包含.exe).
