【问题标题】:Search file with Regular expression使用正则表达式搜索文件
【发布时间】:2015-08-11 13:07:44
【问题描述】:

我有以下递归搜索功能:

public List<FileInfo> Search_Files(String strDir, String line)
{
    List<FileInfo> files = new List<FileInfo>();

    try
    {
         foreach (String strFile in Directory.GetFiles(strDir,line+r))
         {
             files.Add(new FileInfo(strFile));
         }

         foreach (String strSubDir in Directory.GetDirectories(strDir))
         {
             List<FileInfo> sublist = Search_Files(strSubDir, line);

             foreach (FileInfo file_infow in sublist)
             {
                 files.Add(file_infow);
             }
         }
    }
    catch (Exception)
    {
         ...
    }

    return (files);
}

行变量的值看起来像“1234”。 现在我想搜索以下文件:1234c.something 或 1234.something

我创建了以下正则表达式:

Regex r = new Regex("[a-z].* | .*");

我将它添加到行字符串,但它不起作用。为什么这不起作用,我该如何纠正?

【问题讨论】:

  • 您不能将正则表达式传递给.GetDirectories。试试1234c.*(这里,. 是文字点,* 表示任意数量的字符)。不要忘记将签名更改为public List&lt;FileInfo&gt; Search_Files(String strDir, String line, String r),如果line1234,那么r 必须是c.*。它对你有用吗?
  • 我不想只找到 c.* 文件,我想找到 1234[a-z].* 文件。
  • 我明白了,我发布了一个答案,希望它对你有用。

标签: c# regex search


【解决方案1】:

我用过LINQ,试试看

string[] allFiles =  Directory.GetFiles(@"C:\Users\UserName\Desktop\Files");
List<string> neededFiles = (from c in allFiles
                               where Path.GetFileName(c).StartsWith("fileStartName")
                               select c).ToList<string>();

foreach (var file in neededFiles)
{
   // do the tesk you want with the matching files
}

【讨论】:

    【解决方案2】:

    GetDirectoriesGetFiles 方法接受 searchPattern,它不是正则表达式。

    与路径中的文件名匹配的搜索字符串。此参数可以包含有效的文字路径和通配符(*?)字符的组合(请参阅备注),但不支持正则表达式。

    您可以使用以下正则表达式过滤结果:

    var r = new Regex(@"\d{4}.*");
    // var r = new Regex(@"^\d{4}.*"); // Use this if file names should start with the 4 digits.
    files.Add(Directory.GetFiles(strDir)
                .Where(p => r.IsMatch(Path.GetFileName(p)))
                .ToList());
    

    \d{4}.* 正则表达式匹配 4 位数字 (\d{4}) 和任何 0 个或多个字符,但换行符除外。

    【讨论】:

    • 我想你不明白我的情况...文件名不仅仅是1234...它可能是123455、99993、324...现在我想获取每个版本这个id。字符串行“1111”可能的版本有以下两个: 1111[a-z].anything 和 1111.anything 第二个没问题:foreach (String strFile in Directory.GetFiles(strDir,line+".* ")) 但我不知道如何找到第一个。
    • 您不能连接字符串和正则表达式对象,这就是您所做的。至于正则表达式,您可以使用 \d+ 代替数字。如果您只需要匹配 4 个数字,请使用 \d{4}。如果您打算允许上述 2 种模式,则模式仍然相同:\d{4}.* 因为[a-z] 是可选的,对吧?
    • 我已经更改了答案,请看一下(现在,仅根据模式检查文件名。另外,如果您打算获取 开头的文件数字+东西,你需要在模式的开头添加^。如果你对需要匹配的文件的正确正则表达式有问题,请给我留言。你可以在regexstorm.net查看模式。
    【解决方案3】:

    如果你想匹配 '.'您必须将其转义为 '\.'。 '.*' 本身表示任何字符 n 次。在此处查看有关格式的详细信息:https://msdn.microsoft.com/en-us/library/az24scfc(v=vs.110).aspx

    我还建议您使用更严格的正则表达式。如果您知道您的文件名以 1234 开头,请在正则表达式中也使用它。

    【讨论】:

      【解决方案4】:

      有两种方法可以做到这一点。第一种是使用 Windows 搜索过滤器。这是您可以直接传递给GetFiles() 方法的内容。 (EnumerateFiles() 做同样的事情,在这种情况下可能会更快,但这与您的问题无关)。

      Windows 搜索模式使用* 表示“任意数量的任意字符”,? 用于表示单个未知字符。这些实际上不是正则表达式。

      然后您可以执行如下搜索:

      return Directory.EnumerateFiles(strDir, line + "*.*", SearchOption.AllDirectories)
                      .Select(f => new FileInfo(f))
                      .ToList();
      

      第二个是您最初寻找的内容,它使用实际的正则表达式执行 linq 查询。可以这样做:

      Regex pattern = new Regex(line + @".*\..*") 
      // regex says use line, then anything any number of times, 
      // and then a dot and then any chars any amount of times
      
      return Directory.EnumerateFiles(strDir, *.*, SearchOption.AllDirectories)
                      .Where(f => pattern.IsMatch(f))
                      .Select(f => new FileInfo(f))
                      .ToList();
      

      注意:以上两个示例展示了如何将提供的字符串也转换为 FileInfo 对象,就像您的 Search_Files 方法的签名要求在“linq-way”中一样。此外,我正在使用 SearchOption.AllDirectories 标志为您执行递归搜索,而无需您自己编写。

      至于为什么你最初发布的方法不起作用;它有两个问题。

      1. 您正在尝试将正则表达式对象与字符串连接。这是不可能的,因为您希望将正则表达式 pattern 与字符串连接起来。这应该在构建正则表达式对象之前(或内部)完成,如我在示例中所示。

      2. 假设您没有尝试将正则表达式对象与字符串连接,那么您使用的正则表达式模式几乎总是会匹配任何内容。这不会限制任何东西。

      【讨论】:

      • 谢谢,但我以前知道这个解决方案。问题是有类似的文件(如果我搜索“1234”):12344256754325.something 我不想得到这些文件!用你的方法我也得到了这些文件......
      • 您能否更清楚地了解文件名的确切模式?使用我上面的第二个选项对你有用,但你需要改进正则表达式以更好地匹配。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多