c# 嵌套量词 - 模式中的多个"?"

  • 本文关键字:嵌套 量词 模式 c# regex
  • 更新时间 :
  • 英文 :


我正在尝试查找目录中是否至少有一个文件与模式匹配(只使用"?"one_answers"*"通配符),但某些组合不断抛出嵌套限定符错误。例如,TestCashFile_10_12-25-2016????????.c??不起作用。

这些模式来自非技术用户(他们受过这两个通配符基本用法的教育),所以"?"one_answers"*"几乎可以放在文件名的任何地方,我没有太多控制权。

这些图案出了什么问题?

这是运行此regex-的C#代码片段

string fileName = C:TestFilesTestCashFile_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);

更新-这个问题已经解决,但如果它能帮助其他人寻找类似的东西,只是为了澄清-在这种情况下,我想用"?"来表示必须只有一个元素(而不是零或一个元素)。

如果您需要"??"来匹配任意字符中的两个,那么您是对的,您必须使用正则表达式。文件系统通配符将"?"视为"零或任意字符之一"。

但是您不能按照您尝试的方式来做,因为您在向用户请求文件系统通配符——您只是稍微改变了语义。您必须将用户的字符串转换为您想要的正则表达式:

a???.*

必须成为

a.?.?.?..*
  • 每个问号都变成".":任何字符中的一个
  • 每个"."都变成了".",因为未转义的"."是正则表达式中的一个特殊字符
  • 每个">"都必须变成".":任何字符的零个或多个(猜测这个)

file字符串执行此操作,您的.Any(p => Regex.Match(p, file).Success);应该可以工作。

不过,如果运行时速度有点慢,您可能需要编译regex:

file = TranslateWildcardsToRegex(file);
var re = new Regex(file);
var found = Directory.GetFiles("").Any(p => re.IsMatch(p));

我认为这对TranslateWildcardsToRegex():来说是正确的

public static String TranslateWildcardsToRegex(String s)
{
StringBuilder sb = new StringBuilder();
foreach (var ch in s)
{
switch (ch)
{
case '?':
sb.Append(".");
break;
case '*':
sb.Append(".*");
break;
//  Escape a variety of characters that 
//  mean something special in a regex
case '(':
case ')':
case '{':
case '}':
case '[':
case ']':
case '.':
sb.Append("\" + ch);
break;
default:
sb.Append(ch);
break;
}
}
return sb.ToString();
}

更新

在评论中@spender提供了一种更好、更干净的方式来做同样的事情:

var reStr = Regex.Escape(someWildcardThing).Replace(@"?", ".").Replace(@"*", ".*")

这么多年过去了,除了仍然是一个正在恢复的C程序员之外,我没有任何理由不这样做。

?运算符指定前一个元素可以出现0或1次。

https://msdn.microsoft.com/en-us/library/az24scfc(v=vs.110).aspx

?匹配上一个元素零次或一次。"rai?n"ran"rain">

如果你像@Ed Plunkett所说的那样使用Directory.GetFiles中内置的通配符,它的工作原理应该与你想要的类似。

如果你仍然想使用当前的RegEx方法,请执行以下操作:

  • .*-任意数量的字符
  • .{n}-将n替换为所需的字符数
  • .{m,n}-将m替换为期望的最小字符数,将n替换为期望字符的最大字符数

最新更新