如何在PHP中使用RegexIterator [英] How to use RegexIterator in PHP

查看:98
本文介绍了如何在PHP中使用RegexIterator的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have yet to find a good example of how to use the php RegexIterator to recursively traverse a directory.

最终的结果是我想指定一个目录并查找其中包含一些给定扩展名的所有文件。比如说只有html / php扩展名。此外,我想过滤掉类型.Trash-0,.Trash-500等文件夹。

The end result would be I want to specify a directory and find all files in it with some given extensions. Say for example only html/php extensions. Furthermore, I want to filter out folders such of the type .Trash-0, .Trash-500 etc.

<?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/>";
}
?>

到目前为止我得到的结果是:致命错误:带有消息的未捕获异常'UnexpectedValueException' RecursiveDirectoryIterator :: __ construct(/media/hdmovies1/.Trash-0)

Is what I have so far but result in : Fatal error: Uncaught exception 'UnexpectedValueException' with message 'RecursiveDirectoryIterator::__construct(/media/hdmovies1/.Trash-0)

有什么建议吗?

推荐答案

有几种不同的方式来做这样的事情,我会给你两种快速的方法供你选择来自:快速和肮脏,相对更长,更脏(但是,这是一个星期五晚上,所以我们被允许有点疯狂)。

There are a couple of different ways of going about something like this, I'll give two quick approaches for you to choose from: quick and dirty, versus longer and less dirty (though, it's a Friday night so we're allowed to go a little bit crazy).

1 。快速(和脏)

这只需要编写一个正则表达式(可以分成多个)来用来快速过滤文件集合。

This involves just writing a regular expression (could be split into multiple) to use to filter the collection of files in one quick swoop.

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

$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;
}

这种方法有很多问题,尽管它很快就可以实现一个单行(虽然正则表达可能是一个难以破译的。)

This approach has a number of issues, though it is quick to implement being just a one-liner (though the regex might be a pain to decipher).

2。更快(更少脏)

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

A more re-usable approach is to create a couple of bespoke filters (using regex, or whatever you like!) to whittle down the list of available items in the initial RecursiveDirectoryIterator down to only those that you want. The following is only one example, written quickly just for you, of extending the RecursiveRegexIterator.

我们从一个开始基类,其主要工作是保持我们想要过滤的正则表达式,其他所有内容都延迟回 RecursiveRegexIterator 。请注意,该类是 abstract ,因为它实际上并没有任何有用的东西:实际的过滤将由两个类完成,这将扩展这个。此外,它可能被称为 FilesystemRegexFilter ,但没有任何强制它(在此级别)过滤与文件系统相关的类(我选择了一个更好的名称,如果我不是非常困倦。

We start with a base class whose main job is to keep a hold of the regex that we want to filter with, everything else is deferred back to the RecursiveRegexIterator. Note that the class is abstract since it doesn't actually do anything useful: the actual filtering is to be done by the two classes which will extend this one. Also, it may be called FilesystemRegexFilter but there is nothing forcing it (at this level) to filter filesystem-related classes (I'd have chosen a better name, if I weren't quite so sleepy).

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

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

These two classes are very basic filters, acting on the file name and directory name respectively.

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文件。

To put those into practice, the following iterates recursively over the contents of the directory in which the script resides (feel free to edit this!) and filters out the .Trash folders (by making sure that folder names do match the specially crafted regex), and accepting only PHP and HTML files.

$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级(包括起始文件夹):

Of particular note is that since our filters are recursive, we can choose to play around with how to iterate over them. For example, we could easily limit ourselves to only scanning up to 2 levels deep (including the starting folder) by doing:

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

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

It is also super-easy to add yet more filters (by instantiating more of our filtering classes with different regexes; or, by creating new filtering classes) for more specialised filtering needs (e.g. file size, full-path length, etc.).

P.S。嗯,这个答案有点唠叨;我尽量保持简洁(甚至删除大量的超级唠叨)。如果最终结果使得答案不一致,请道歉。

这篇关于如何在PHP中使用RegexIterator的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆