регулярное выражение не работает должным образом при сопоставлении имен файлов с подстановочными знаками - PullRequest
0 голосов
/ 18 июня 2020

Я пишу функцию PHP, которая принимает массив имен файлов и удаляет имена файлов из массива, если они не соответствуют набору критериев, введенных пользователем. Функция выполняет итерацию по массиву и сравнивает каждое значение с регулярным выражением. Регулярное выражение формируется путем вставки переменных из пользовательского ввода. Если пользователь не указал переменную, вместо переменной вставляются подстановочные знаки регулярного выражения. Имена файлов очень систематичны c, например 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 symbol
if ($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"

Ожидаемый результат: Массив содержит только файлы с буквой L в месте раздела (YEAR-MONTH-**SECTION**-NUMBER.txt)

Результирующий массив:

{"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 ]

1 голос
/ 19 июня 2020

Основная проблема состоит в том, что 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);
1 голос
/ 18 июня 2020

Проблема заключается в использовании unset () внутри al oop. На следующей итерации индекс уже не тот, что был до того, как вы испортили массив с помощью 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();
}
?>
...