使用文字数字似乎打破了RegexIterator

时间:2014-02-13 03:24:29

标签: php regex iterator

当我将数字指定为正则表达式的一部分时,我有一段PHP代码停止工作。我相信他们不需要逃脱,但肯定是错的。

代码如下

$dir = new RecursiveDirectoryIterator($IMAGES_DIR);
$iter = new RecursiveIteratorIterator($dir);
$rx = new RegexIterator($iter, $IMG_MASK, RecursiveRegexIterator::GET_MATCH);

$images = array();
foreach ($rx as $r) {
    $images[] = $r[0];
}
var_dump($images);

在与PHP文件相同的目录中是一个名为images的目录,其布局如下:

images/
    1.png
    2.png
    3.png
    test/
        4.png
        5.png
        6.png

在代码中,常量$IMAGES_DIR = 'images/'

$IMG_MASK = /^.+\.png$/一切正常时 - 转储包含所有6张图像。

$IMG_MASK = /^[1-3]\.png$//^1\.png$//^\1\.png$/(我没想到最后一个工作,但是给它一个镜头)时,转储是一个空数组。

正如我所反对的所有测试人员中的正则表达式似乎都很好。我错过了什么?

1 个答案:

答案 0 :(得分:1)

这里看起来发生的事情是$IMAGES_DIR中的目录本身包含在迭代中返回到$r的模式中。使用您的工作模式,如果您在循环中print_r($r);,您将看到匹配的模式:

array(6) {
  [0]=>
  string(19) "./images/test/4.png"
  [1]=>
  string(19) "./images/test/6.png"
  [2]=>
  string(19) "./images/test/5.png"
  [3]=>
  string(14) "./images/3.png"
  [4]=>
  string(14) "./images/1.png"
  [5]=>
  string(14) "./images/2.png"
}

因此,您需要构建表达式以合并目录,或者忽略它而不是锚定^。您尝试的模式匹配完全模式,如1.png,但它正在测试的输入字符串是实际的./images/1.png

相反,我建议使用

$IMG_MASK = '#/[1-3]\.png$#';

此模式不会^锚定字符串的开头,而是在数字前的/开始匹配。

如果您有兴趣获取完整路径,请将.+恢复到开头,然后在数字前使用DIRECTORY_SEPARATOR

$IMG_MASK = '#.+' . DIRECTORY_SEPARATOR . '[1-3]\.png$#';

这会匹配任何内容(.+)到/(或您平台的分隔符),然后匹配单个数字和.png。结果是一个数组:

Array
(
    [0] => ./images/3.png
    [1] => ./images/1.png
    [2] => ./images/2.png
)

当然,如果您希望./images/test/中的这些图片调整正则表达式,请使用\d\.png来匹配任何数字,而不仅仅是[1-3]

模式

$IMG_MASK = '#.+' . DIRECTORY_SEPARATOR . '\d\.png$#';

...生产:

Array
(
    [0] => ./images/test/4.png
    [1] => ./images/test/6.png
    [2] => ./images/test/5.png
    [3] => ./images/3.png
    [4] => ./images/1.png
    [5] => ./images/2.png
)