php - 如何在 PHP 中使用 RegexIterator

标签 php regex iterator spl

我还没有找到一个很好的例子来说明如何使用 php RegexIterator 递归遍历目录。

最终结果是我想指定一个目录并在其中找到所有具有给定扩展名的文件。例如仅 html/php 扩展名。此外,我想过滤掉 .Trash-0、.Trash-500 等类型的文件夹。

<?php 
$Directory = new RecursiveDirectoryIterator("/var/www/dev/");
$It = new RecursiveIteratorIterator($Directory);
$Regex = new RegexIterator($It,'/^.+\.php$/i',RecursiveRegexIterator::GET_MATCH);

foreach($Regex as $v){
    echo $value."<br/>";
}
?>

是我到目前为止所拥有的,但导致: fatal error :未捕获异常“UnexpectedValueException”,消息为“RecursiveDirectoryIterator::__construct(/media/hdmovies1/.Trash-0)”

有什么建议吗?

最佳答案

有几种不同的方法可以解决这样的问题,我将提供两种快速方法供您选择:快速而肮脏的方法,以及更长且不那么肮脏的方法(不过,这是星期五晚上,所以我们允许有点疯狂)。

<强>1。快速(脏)

这只涉及编写一个正则表达式(可以拆分为多个)用于一次性过滤文件集合。

(只有两行注释对这个概念非常重要。)

$directory = new RecursiveDirectoryIterator(__DIR__);
$flattened = new RecursiveIteratorIterator($directory);

// Make sure the path does not contain "/.Trash*" folders and ends eith a .php or .html file
$files = new RegexIterator($flattened, '#^(?:[A-Z]:)?(?:/(?!\.Trash)[^/]+)+/[^/]+\.(?:php|html)$#Di');

foreach($files as $file) {
    echo $file . PHP_EOL;
}

这种方法有很多问题,尽管它只是一个单行代码实现起来很快(尽管正则表达式可能很难破译)。

<强>2。不太快(也不太脏)

一种更可重用的方法是创建几个定制的过滤器(使用正则表达式,或任何你喜欢的!)以将初始 RecursiveDirectoryIterator 中的可用项目列表缩减为仅那些你要的那个。以下只是为您快速编写的扩展 RecursiveRegexIterator 的一个示例。

我们从一个基类开始,它的主要工作是保留我们要过滤的正则表达式,其他一切都推迟回 RecursiveRegexIterator。请注意,该类是抽象的,因为它实际上 任何有用的事情:实际的过滤将由扩展该类的两个类完成。此外,它可能被称为 FilesystemRegexFilter 但没有什么强制它(在这个级别)过滤与文件系统相关的类(如果我不是那么困的话,我会选择一个更好的名字) .

abstract class FilesystemRegexFilter extends RecursiveRegexIterator {
    protected $regex;
    public function __construct(RecursiveIterator $it, $regex) {
        $this->regex = $regex;
        parent::__construct($it, $regex);
    }
}

这两个类是非常基本的过滤器,分别作用于文件名和目录名。

class FilenameFilter extends FilesystemRegexFilter {
    // Filter files against the regex
    public function accept() {
        return ( ! $this->isFile() || preg_match($this->regex, $this->getFilename()));
    }
}

class DirnameFilter extends FilesystemRegexFilter {
    // Filter directories against the regex
    public function accept() {
        return ( ! $this->isDir() || preg_match($this->regex, $this->getFilename()));
    }
}

为了将这些付诸实践,以下代码递归遍历脚本所在目录的内容(请随意编辑它!)并过滤掉 .Trash 文件夹(通过确保文件夹名称​​确实匹配特制的正则表达式),并且只接受 PHP 和 HTML 文件。

$directory = new RecursiveDirectoryIterator(__DIR__);
// Filter out ".Trash*" folders
$filter = new DirnameFilter($directory, '/^(?!\.Trash)/');
// Filter PHP/HTML files 
$filter = new FilenameFilter($filter, '/\.(?:php|html)$/');

foreach(new RecursiveIteratorIterator($filter) as $file) {
    echo $file . PHP_EOL;
}

特别值得注意的是,由于我们的过滤器是递归的,我们可以选择尝试如何迭代它们。例如,我们可以很容易地限制自己只扫描最多 2 层深度(包括起始文件夹):

$files = new RecursiveIteratorIterator($filter);
$files->setMaxDepth(1); // Two levels, the parameter is zero-based.
foreach($files as $file) {
    echo $file . PHP_EOL;
}

添加更多过滤器(通过使用不同的正则表达式实例化更多过滤类;或者,通过创建新的过滤类)来满足更专业的过滤需求(例如文件大小、完整路径长度等)也非常容易.).

附言嗯,这个答案有点啰嗦;我试图让它尽可能简洁(甚至删除了大量的 super 废话)。如果最终结果使答案不连贯,我们深表歉意。

关于php - 如何在 PHP 中使用 RegexIterator,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3321547/

相关文章:

php - 将数据插入到不同的表中

Java (Android) 相当于 PHP $$x

regex - 使用 sed 查找和替换一系列数字

c++ - 为自定义迭代器特化 std::copy

c++ - 双向链表后向指针

php - 从 mysql 数据库中发出一个多词的排序

php - 在 PHP 中使用 HybridAuth 时如何更新用户状态?

c++ - 正则表达式可以,但不起作用

javascript - JavaScript 中的正则表达式 : match multiple substrings at the beginning of a string?

C++ 流迭代器与容器迭代器