C# c“嵌套量词-多个”&引用;在模式中
我试图查找目录中是否至少有一个文件与模式匹配(仅使用“?”和“*”通配符),但某些组合会不断抛出嵌套限定符错误。例如-C# c“嵌套量词-多个”&引用;在模式中,c#,regex,C#,Regex,我试图查找目录中是否至少有一个文件与模式匹配(仅使用“?”和“*”通配符),但某些组合会不断抛出嵌套限定符错误。例如-TestCashFile\u 10\u 12-25-2016?????.c???不起作用 这些模式来自非技术用户(他们接受过这两个通配符的基本用法方面的教育),因此“?”和“*”可以在文件名中的几乎任何地方出现,我没有太多的控制权 这些模式有什么问题 这是运行此正则表达式的C#代码段- string fileName = C:\TestFiles\TestCashFile_10_
TestCashFile\u 10\u 12-25-2016?????.c???
不起作用
这些模式来自非技术用户(他们接受过这两个通配符的基本用法方面的教育),因此“?”和“*”可以在文件名中的几乎任何地方出现,我没有太多的控制权
这些模式有什么问题
这是运行此正则表达式的C#代码段-
string fileName = C:\TestFiles\TestCashFile_10_12-25-2016????????.c??'
string directory = Path.GetDirectoryName(fileName);
string[] temp = fileName.Split('\\');
string file = temp[temp.Length - 1];
var found = Directory.GetFiles(directory).Any(p => Regex.Match(p, file).Success);
更新-问题已经解决,但如果它有助于其他人寻找类似的东西,请澄清-在本例中,我希望“?”表示必须只有一个元素(与零或一个元素相反) 操作符指定上一个元素可以出现0次或1次 ??与上一个元素零次或一次匹配。“rai?n”“ran”“rain” 如果您像@Ed Plunkett所说的那样使用内置于
Directory.GetFiles
中的通配符,那么它的工作原理应该与您正在寻找的类似
如果您仍然希望对RegEx使用当前方法,请执行以下操作:
-任意数量的字符*
-将{n}
替换为预期的字符数n
-将{m,n}
替换为预期的最小字符数,将n替换为预期的最大字符数m
a???.*
必须成为
a.?.?.?\..*
- 每个问号变成“.”:正好是任何字符中的一个李>
- 每个“.”变为“.”,因为unescaped“.”是正则表达式中的特殊字符
- 每个“”都必须变为“”:任何字符的零个或多个(猜测此字符)
文件
字符串和的.Any(p=>Regex.Match(p,file.Success)执行该操作代码>应该可以工作
不过,如果运行时速度有点慢,您可能需要编译正则表达式:
file = TranslateWildcardsToRegex(file);
var re = new Regex(file);
var found = Directory.GetFiles("").Any(p => re.IsMatch(p));
我认为这适用于TranslateWildcardsToRegex()
:
更新
在评论中@spender提供了一种更好、更干净的方法来做同样的事情:
var reStr = Regex.Escape(someWildcardThing).Replace(@"\?", ".").Replace(@"\*", ".*")
我自己没有理由不这样做,除了在这么多年后仍然是一名恢复中的C程序员 看。。有什么我遗漏的吗?您似乎在使用文件系统通配符,就好像它们是正则表达式一样。他们不是。这不可能。文件通配符和正则表达式不是一回事。不管怎样,@EdPlunkett说的话在你尝试重新发明轮子之前应该仔细考虑。@EdPlunkett,@spender我刚刚试过Directory.GetFiles(Directory,file)
,它似乎更像C:\TestFiles\TestCashFile\u 10\u 12-25-2016*.C*
@EdPlunkett我只是试过你建议的方法,但根本不起作用。TestCashFile_10_12-25-2016.c??根据您的建议返回文件“TestCashFile_10_12-25-2016.csv”、“TestCashFile_10_12-25-2016_B.csv”等。谢谢。我的错误是,我曾设想,?
将确保每个?
都必须有一个元素。我只是尝试将其更改为TestCashFile_10_12-25-2016{2}.c{2},但它也不会返回任何结果。文件夹中存在名为“TestCashFile\u 10\u 12-25-2016\u D.csv”和“TestCashFile\u 10\u 12-25-2016\u D.csv”等的文件。您需要
(句点/点),它指示本例中的任何字符。因此,请尝试TestCashFile\u10\u12-25-2016.{2}\\\.c.{2}
。您还需要在文件扩展名的
上添加转义斜杠,以将其视为实际字符,尽管这会带来问题,因为您已经在\\上拆分了…谢谢。这很有效。嵌套的量词异常似乎也已通过此更改自行解决。这是一个System.ArgumentException,带有消息“嵌套的量词…”,我在问题中的模式是在Regex.Match上抛出的。这似乎是关于stackoverflow的一个非常常见的问题,但我无法为我的具体案例找到解决方案。很高兴知道修复正则表达式也解决了这个问题。哦,好吧,我明白了:根据正则表达式语法规则,“a?*”是一个异想天开的请求:“零或多个零或一个a”。所以不管出于什么原因,他们提出了一个例外。现在,通过字符串操作将通配符转换为属性regex,这是不可能发生的。“a?*”变为“a…”,这是合法的。这也提醒了我——我需要对translate函数做更多的修改。@Achiles我刚刚添加了一个更新版本的TranslateWildcardsToRegex()
。它解决了一些可能会打破旧字符的特殊字符。@EdPlunkett我不由得感到,使用Regex.Escape
,这一点可以显著改进。难道不能用像Regex.Escape(someWildcardThing.Replace(@“\?”,“)。Replace(@“\*”,“*”)
这样简单的东西来完成吗?
var reStr = Regex.Escape(someWildcardThing).Replace(@"\?", ".").Replace(@"\*", ".*")