【问题标题】:PHP Recursive regex filter iterator iteratorPHP Recursive regex filter iterator iterator
【发布时间】:2018-02-02 02:25:46
【问题描述】:

我只是尝试循环遍历目录中的所有文件,递归地过滤到仅与模式匹配的文件。

原来RegexIterator 给了你正则表达式匹配对象,但我想要SplInfo 对象。

这就是我所拥有的:

class RegexFilterIterator extends RecursiveFilterIterator {

    private $pattern;

    public function __construct(RecursiveIterator $iterator, $pattern) {
        parent::__construct($iterator);
        $this->pattern = $pattern;
    }


    public function accept() {
        return preg_match($this->pattern, $this->current()->getFilename()) > 0;
    }
}

$dir = new RecursiveDirectoryIterator($argv[1]);
$regex = new RegexFilterIterator($dir, '/\.php5?\z/i');
$it = new RecursiveIteratorIterator($regex);



foreach($it as $foo) {
   echo $foo->getPathname().PHP_EOL;
}

但这似乎不是递归的。

我相信这是因为 \RegexFilterIterator::accept 实际上也被提供了目录,我拒绝它们,因为它们不以 .php 结尾。

很容易解决,对吧?稍微修改一下:

public function accept() {
    return $this->current()->isDir() || preg_match($this->pattern, $this->current()->getFilename()) > 0;
}

现在它崩溃了:

PHP 致命错误:未捕获的 ArgumentCountError:函数 RegexFilterIterator::__construct() 的参数太少,通过了 1 个,而 bleep

中预期正好有 2 个

这对我来说没有任何意义。为什么要尝试自己构建更多 RegexFilterIterator 实例,它是如何搞砸的??

我会将RegexFilterIterator 放在 RecursiveIteratorIterator 之后,但它对我大喊大叫:

PHP 致命错误:未捕获的 TypeError:传递给 RegexFilterIterator::__construct() 的参数 1 必须实现接口 RecursiveIterator,给定 RecursiveIteratorIterator 的实例

所以...我不知道你应该如何使用这些类。

我如何递归目录中的所有文件,并使用简单的正则表达式过滤它们,给我一个生成 SplInfo 对象的生成器/可迭代对象?

【问题讨论】:

    标签: php


    【解决方案1】:

    在php.net的cmets中找到this,由“sun”发帖,稍微改进了一下:

    $directory = new \RecursiveDirectoryIterator($argv[1], \FilesystemIterator::SKIP_DOTS);
    $filter = new \RecursiveCallbackFilterIterator($directory, function ($current, $key, $iterator) {
        return $current->isDir() || preg_match('/\.php5?\z/',$current->getPathname()) > 0;
    });
    $iterator = new \RecursiveIteratorIterator($filter);
    
    foreach($iterator as $file) {
       echo $file->getPathname().PHP_EOL;
    }
    

    RecursiveCallbackFilterIterator 似乎更容易使用,而不是扩展RecursiveFilterIterator。还有一个方便的FilesystemIterator::SKIP_DOTS 标志。

    【讨论】:

      【解决方案2】:

      我意识到我们可以只使用生成器函数来清理这些废话,而不是使用迭代器接口:

      function readDirRecursive($dir, $pattern=null) {
          $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS));
          foreach($iterator as $it) {
              if($it->isFile() && ($pattern===null || preg_match($pattern, $it->getPathname()))) {
                  yield $it;
              }
          }
      }
      
      
      $iterator = readDirRecursive($argv[1],'/\.php5?\z/');
      
      foreach($iterator as $file) {
         echo $file->getPathname().PHP_EOL;
      }
      

      【讨论】:

      • 有点挫败你最初想要做的事情。你真的不需要生成器,一个 foreach 就可以工作:/
      • @LawrenceCherone 怎么样?哦..您的意思是我可以将if 直接放在我的foreach 中?是的......我想是的,除非我想这样做一大堆。无论如何,我确实想出了如何使用那些愚蠢的类,将在几秒钟内发布。
      猜你喜欢
      • 2013-05-27
      • 2012-11-17
      • 2010-11-21
      • 2010-10-14
      • 1970-01-01
      • 2020-04-20
      • 2018-01-19
      • 1970-01-01
      相关资源
      最近更新 更多