我正在尝试解析文件名并删除括号中的潜在数字(当多个具有相同基本名称的文件时),但是只有最后一个
以下是一些预期结果:
Test
==> Test
Test (1)
==> Test
Test (1) (2)
==> Test (1)
Test (123) (232)
==> Test (123)
Test (1) foo
==> Test (1) foo
我尝试使用此正则表达式:(.*)( ?\(\d+\))+
,但测试1失败。
我也尝试过:(.*)( ?\(\d+\))?
,但只有第一个测试成功。
我怀疑正则表达式中的量词有问题,但我找不到确切的内容。
如何修复我的正则表达式?
答案 0 :(得分:4)
我的猜测是,您可能希望设计一个类似于以下内容的表达式:
^(.*?)\s*(\(\s*\d+\)\s*)?$
using System;
using System.Text.RegularExpressions;
public class Example
{
public static void Main()
{
string pattern = @"^(.*?)\s*(\(\s*\d+\)\s*)?$";
string input = @"Test
Test (1)
Test (1) (2)
Test (1) (2) (3)
Test (1) (2) (3) (4)
";
RegexOptions options = RegexOptions.Multiline;
foreach (Match m in Regex.Matches(input, pattern, options))
{
Console.WriteLine("'{0}' found at index {1}.", m.Value, m.Index);
}
}
}
该表达式在regex101.com的右上角进行了解释,如果您想探索/简化/修改它,在this link中,您可以观察到它如何与某些示例输入匹配,如果你喜欢。
jex.im可视化正则表达式:
答案 1 :(得分:2)
只用一个负数。前瞻:
\s*\([^()]+\)(?!.*\([^()]+\))
\s* # whitespaces, eventually
\([^()]+\) # (...)
(?!.*\([^()]+\)) # neg. lookahead, no (...) must follow
答案 2 :(得分:2)
作为替代方案,您可以使用字符串结尾/行锚:
\s*\(\d+\)$
string resultString = null;
try {
resultString = Regex.Replace(subjectString, @"\s*\(\d+\)$", "", RegexOptions.Multiline);
} catch (ArgumentException ex) {
// Syntax error in the regular expression
}
\s*
*
\(
\d+
+
\)
$
答案 3 :(得分:1)
如果只希望第二个表达式可以做,则可以一起避免使用正则表达式:
string example = @"Test (1) (2) (3) (4)";
public string GetPathName(string input)
{
var position = input.LastIndexOf('(');
if(position == -1)
return input;
return example.Substring(0, position);
}
您知道左括号将始终位于结尾名称的开头,那么为什么不找到该索引的索引,然后从零位置获取其余的索引呢?我知道您要求使用正则表达式,但是如果不需要它,为什么要为此过度设计呢?
答案 4 :(得分:1)
您可以使用第一个模式(.*)( ?\(\d+\))+
并仅替换为第一个捕获组。
要对其进行优化,可以在最后一个组之后删除量词+
,并省略第二个捕获组。
这将通过匹配直到字符串的末尾,然后回溯直到最后一次出现带数字的括号,来删除最后一个带有数字的括号。
在替换中,使用第一个捕获组:
^(.*) \(\d+\)
说明
^
字符串的开头(.*)
捕获组1,匹配任何char 0次以上 (\d+)
匹配空间,(
1个以上的数字)
答案 5 :(得分:-1)