C# 正则表达式,包括结果中应该是非捕获组的内容
下面是一个简单的测试,我试图获取Regex模式,这样它就可以在没有“.exe”后缀的情况下拖动可执行文件名。C# 正则表达式,包括结果中应该是非捕获组的内容,c#,.net,regex,C#,.net,Regex,下面是一个简单的测试,我试图获取Regex模式,这样它就可以在没有“.exe”后缀的情况下拖动可执行文件名。 似乎我的非捕获组设置(?:\\.exe)不起作用,或者我误解了它的工作原理。 和都显示相同的结果,前者确认“(?:\.exe)”是非捕获匹配。 有没有想过我做错了什么 // test variable for what i would otherwise acquire from Environment.CommandLine var testEcl = "\"D:\\src\\repo
似乎我的非捕获组设置
(?:\\.exe)
不起作用,或者我误解了它的工作原理。和都显示相同的结果,前者确认“(?:\.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
//测试变量,否则我将从Environment.CommandLine获取
var testEcl=“\”D:\\src\\repos\\myprj\\bin\\Debug\\MyApp.exe\/?”
var asmName=Regex.Match(Environment.CommandLine,@“(?[^\\]+)(?\.exe)”,
RegexOptions.IgnoreCase)。组[“fname”]。值;
//获取所需的“MyApp”结果
/eoq将匹配未捕获组,但不会捕获它,因此如果您想要未捕获的部分,则应访问捕获组,而不是整个匹配 您可以在中访问组
var asmName = Regex.Match(testEcl, @"([^\\]+)(?:\.exe)", RegexOptions.IgnoreCase);
asmName.Groups[1].Value
正则表达式的演示可以找到A(?:…)
是一个非捕获组,它匹配并仍然使用文本。这意味着该组匹配的文本部分仍然添加到整体匹配值中
一般来说,如果你想匹配某样东西而不是消费,你需要使用lookarounds。因此,如果您需要匹配后跟特定字符串的内容,请使用正向前瞻,(?=…)
构造:
some_pattern(?=specific string) // if specific string comes immmediately after pattern
some_pattern(?=.*specific string) // if specific string comes anywhere after pattern
如果之前需要匹配但“从匹配中排除”某些特定文本,请使用正向查找:
见
详细信息
-捕获组1:除([^\\]+)
\
-文字点\。
-文本exe
子字符串exe
m.Groups[1].Value
,而不是整个m.Value
(包含.exe
)。您使用的是。重点是这里的词组;该组不捕获.exe
,但通常正则表达式仍然捕获
您可能希望使用,它只是断言字符串必须满足匹配有效的条件,尽管没有捕获该条件
换句话说,您希望在组开始时使用(?=
),而不是(?:
。
前者仅在枚举时使用;在您的示例中,您只是在使用,因此普通组(\.exe)
和非捕获组(?:\.exe)
之间没有区别
为了看到区别,请考虑这个测试程序:
static void Main(string[] args)
{
var positiveInput = "\"D:\\src\\repos\\myprj\\bin\\Debug\\MyApp.exe\" /?";
Test(positiveInput, @"[^\\]+(\.exe)");
Test(positiveInput, @"[^\\]+(?:\.exe)");
Test(positiveInput, @"[^\\]+(?=\.exe)");
var negativeInput = "\"D:\\src\\repos\\myprj\\bin\\Debug\\MyApp.dll\" /?";
Test(negativeInput, @"[^\\]+(?=\.exe)");
}
static void Test(String input, String pattern)
{
Console.WriteLine($"Input: {input}");
Console.WriteLine($"Regex pattern: {pattern}");
var match = Regex.Match(input, pattern, RegexOptions.IgnoreCase);
if (match.Success)
{
Console.WriteLine("Matched: " + match.Value);
for (int i = 0; i < match.Groups.Count; i++)
{
Console.WriteLine($"Groups[{i}]: {match.Groups[i]}");
}
}
else
{
Console.WriteLine("No match.");
}
Console.WriteLine("---");
}
第一个正则表达式(@“[^\\]+(\.exe)”
)具有与普通组相同的\.exe。
当我们枚举Groups属性时,我们看到.exe
确实是在输入中捕获的一个组。
(请注意,整个正则表达式本身就是一个组,因此Groups[0]
等于Value
)
第二个正则表达式(@“[^\\]+(?:\.exe)”
)就是您的问题中提供的。
与上一个场景相比,唯一的区别是Groups属性不包含.exe
作为其条目之一
第三个正则表达式(@“[^\\]+(?=\.exe)”
)是我建议您使用的。
现在,输入的.exe
部分根本不会被正则表达式捕获,但是正则表达式将不会匹配字符串,除非它以.exe
结尾,如第四个场景所示。从var testEcl=“\”D:\\src\\repos\\myprj\\bin\\Debug\\MyApp.exe\”获取MyApp
您可以使用Path.GetFileName
作为string directory=Path.GetFileName(testEcl);
@Ashik,感谢您基于非正则表达式的建议。已尝试的Path.GetFileName()和.GetFileNameWithoutExtension()都会抛出System.ArgumentException“路径中的非法字符”。结果。您的路径包括“
在开头和结尾。请尝试删除引号,谢谢您的响应。我正在查找匹配的捕获部分,而不是通过(?:)
设置表示为非捕获组的部分。当我尝试上述检索.Groups[1]时,值会生成”“空字符串和.Groups[0].Value与我仅拉动.Value和Groups.Count时得到的结果相同。感谢您,现在它可以工作了。根据其他响应,我甚至不需要(?:)非捕获设置,在这种情况下,无论是否有,都不会影响未命名捕获组()设置将所需匹配放入组[1]。Value
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);
static void Main(string[] args)
{
var positiveInput = "\"D:\\src\\repos\\myprj\\bin\\Debug\\MyApp.exe\" /?";
Test(positiveInput, @"[^\\]+(\.exe)");
Test(positiveInput, @"[^\\]+(?:\.exe)");
Test(positiveInput, @"[^\\]+(?=\.exe)");
var negativeInput = "\"D:\\src\\repos\\myprj\\bin\\Debug\\MyApp.dll\" /?";
Test(negativeInput, @"[^\\]+(?=\.exe)");
}
static void Test(String input, String pattern)
{
Console.WriteLine($"Input: {input}");
Console.WriteLine($"Regex pattern: {pattern}");
var match = Regex.Match(input, pattern, RegexOptions.IgnoreCase);
if (match.Success)
{
Console.WriteLine("Matched: " + match.Value);
for (int i = 0; i < match.Groups.Count; i++)
{
Console.WriteLine($"Groups[{i}]: {match.Groups[i]}");
}
}
else
{
Console.WriteLine("No match.");
}
Console.WriteLine("---");
}
Input: "D:\src\repos\myprj\bin\Debug\MyApp.exe" /?
Regex pattern: [^\\]+(\.exe)
Matched: MyApp.exe
Groups[0]: MyApp.exe
Groups[1]: .exe
---
Input: "D:\src\repos\myprj\bin\Debug\MyApp.exe" /?
Regex pattern: [^\\]+(?:\.exe)
Matched: MyApp.exe
Groups[0]: MyApp.exe
---
Input: "D:\src\repos\myprj\bin\Debug\MyApp.exe" /?
Regex pattern: [^\\]+(?=\.exe)
Matched: MyApp
Groups[0]: MyApp
---
Input: "D:\src\repos\myprj\bin\Debug\MyApp.dll" /?
Regex pattern: [^\\]+(?=\.exe)
No match.
---