为了账号安全,请及时绑定邮箱和手机立即绑定

将文件名与通配符匹配时,正则表达式无法按预期工作

将文件名与通配符匹配时,正则表达式无法按预期工作

PHP
一只斗牛犬 2023-06-18 16:25:40
我正在编写一个 PHP 函数,它接受一个文件名数组,如果文件名与用户输入的一组条件不匹配,则从该数组中删除文件名。该函数遍历数组并将每个值与正则表达式进行比较。正则表达式是通过插入来自用户输入的变量而形成的。如果用户没有指定变量,则在变量的位置插入正则表达式通配符。文件名都非常系统化,所以2020-06-N-1.txt我确切地知道文件名和用户输入中预期有多少个字符。但是,当我运行代码时,与正则表达式不匹配的文件名仍在数组中。删除了一些不匹配的文件名,但保留了许多其他文件名。下面是我的部分 PHP 代码。任何帮助表示赞赏。function fileFilter() {    global $fileArray, $fileFilterPattern;        /* The loop starts at 2 and goes to count()-1 because the first 2 elements were removed earlier with unset */    for ($j = 2; $j < count($fileArray) - 1; $j++) {        if(!(preg_match($fileFilterPattern, $fileArray[$j]))) {            unset($fileArray[$j]);        }    }    return;}// If user does not provide a filter value, it gets converted into wildcard symbolif ($month == '') {    $month = '..';}if ($year == '') {    $year = '....';}if ($section == '') {    $section = '.';}$fileFilterPattern = "/{$year}-{$month}-{$section}-.\.txt/";/* function only runs if user applied at least one filter */if (!($month == '..' && $year == '....' && $section == '.')) {    fileFilter();}下面我提供了一个示例,说明数组如何包含不匹配的元素。我使用我的输出数组echo json_encode($fileArray);我的输入:月是"" 年是""节是"L"预期结果:数组仅包含在部分 spot ( YEAR-MONTH-**SECTION**-NUMBER.txt)中具有 L 的文件结果数组:{"8":"2020-06-L-1.txt","9":"2020-06-L-2.txt","10":"2020-06-L-3.txt","11":"2020-06-L-4.txt","12":"2020-06-L-5.txt","15":"2020-06-N-3.txt","16":"2020-06-N-4.txt","17":"2020-06-N-5.txt","18":"2020-06-N-6.txt","19":"2020-06-O-1.txt","20":"2020-06-O-2.txt","21":"2020-06-O-3.txt","22":"2020-06-O-4.txt","23":"2020-06-S-1.txt","24":"2020-06-S-2.txt","25":"2020-06-S-3.txt"}
查看完整描述

2 回答

?
喵喵时光机

TA贡献1846条经验 获得超7个赞

问题是在循环中使用 unset() 。在下一次迭代中,索引不再与您使用 unset() 破坏数组之前的索引相同。有时,您可以使用 array_values() 来处理这个问题,但在这种情况下,只构建第二个仅包含您想要的值的数组会更简单。以下代码有效。我使用 array_values() 只是为了获取您提供的字符串并使索引恢复正常。


也就是说,由于“前 2 个元素之前已使用 unset 删除”,因此您需要在到达此部分之前对数组运行 array_values() 。


<?php


$str ='{"8":"2020-06-L-1.txt","9":"2020-06-L-2.txt","10":"2020-06-L-3.txt","11":"2020-06-L-4.txt","12":"2020-06-L-5.txt","15":"2020-06-N-3.txt","16":"2020-06-N-4.txt","17":"2020-06-N-5.txt","18":"2020-06-N-6.txt","19":"2020-06-O-1.txt","20":"2020-06-O-2.txt","21":"2020-06-O-3.txt","22":"2020-06-O-4.txt","23":"2020-06-S-1.txt","24":"2020-06-S-2.txt","25":"2020-06-S-3.txt"}';


$fileArray = json_decode($str, true);

$fileArray = array_values($fileArray);


echo '<p>fileArray: ';

var_dump($fileArray);

echo '</p>';


function fileFilter() {

    global $fileArray, $fileFilterPattern;

    $filteredArray = [];


    for ($j = 0; $j < count($fileArray); $j++) {

        if(preg_match($fileFilterPattern, $fileArray[$j]) === 1) {

            //unset($fileArray[$j]);

            array_push($filteredArray, $fileArray[$j]);

        }

    }

    echo '<p>filteredArray: ';

    var_dump($filteredArray);

    echo '</p>';

    //return;

}


$month =='';

$year = '';

// If user does not provide a filter value, it gets converted into wildcard symbol

if ($month == '') {

    $month = '..';

}

if ($year == '') {

    $year = '....';

}

if ($section == '') {

    $section = '.';

}


$section = 'L';


$fileFilterPattern = "#{$year}-{$month}-{$section}-.\.txt#";


echo '<p>fileFilterPattern: ';

var_dump($fileFilterPattern);

echo '</p>';


/* function only runs if user applied at least one filter */

if (!($month == '..' && $year == '....' && $section == '.')) {

    fileFilter();

}

?>


查看完整回答
反对 回复 2023-06-18
?
慕桂英546537

TA贡献1848条经验 获得超10个赞

主要问题是count每次减少unset,所以你应该定义一次计数。假设-1和$j = 2对于您的场景是正确的:


$count = count($fileArray) - 1;


for ($j = 2; $j < $count; $j++) {

    if(!(preg_match($fileFilterPattern, $fileArray[$j]))) {

        unset($fileArray[$j]);

    }

}

还有其他方法,您不必假设然后跟踪密钥:


foreach($fileArray as $k => $v) {

    if(!preg_match($fileFilterPattern, $v)) {

        unset($fileArray[$k]);

    }

}

我会摆脱你的fileFilter功能并改用这个方便的功能,它将返回与模式匹配的所有项目:


$fileArray = preg_grep($fileFilterPattern, $fileArray);


查看完整回答
反对 回复 2023-06-18
  • 2 回答
  • 0 关注
  • 204 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信