Intereting Posts
unlink PHP работает, когда файл находится в корне, а не если файл находится в папке jquery для заполнения нескольких выпадающих списков из базы данных Зачем мне нужно использовать многие функции очистки, чтобы очистить выходной буфер (используя wamp, PHP) Переключение php на mysqli: проблема num_rows Как использовать корпус переключателя в шаблоне Mustache? Рекомендации по проектированию каркаса Различное поведение функции uasort в PHP 5.5 и PHP 7.0 Соединение php с пулом mysql Анализ данных из базы данных Викисловаря XML в базе данных MySQL с использованием PHP папка как субдомен на клике Почему мои переменные выходят из сферы действия? PHP Как перевести конкатенированную строку в шаблон твига, используя переводчик Symfony2 Как предотвратить загрузку файлов PHP? И каким образом кто-то может их загрузить? Как я могу добавить новую строку в таблицу каждые 10 столбцов автоматически? PHP: получить последнюю строку в базе данных с помощью mysql

Регулярное выражение для соответствия неограниченному числу параметров

Я хочу иметь возможность анализировать пути файлов, подобные этому:

/var/www/index.(htm|html|php|shtml) 

в упорядоченный массив:

  array("htm", "html", "php", "shtml") 

а затем составить список альтернатив:

 /var/www/index.htm /var/www/index.html /var/www/index.php /var/www/index.shtml 

Прямо сейчас у меня есть инструкция preg_match которая может разделить две альтернативы:

  preg_match_all ("/\(([^)]*)\|([^)]*)\)/", $path_resource, $matches); 

Может ли кто-нибудь дать мне указатель, как продлить это, чтобы принять неограниченное количество альтернатив (по крайней мере два)? Только в отношении регулярного выражения, остальное, с чем я могу иметь дело.

Это правило:

  • Список должен начинаться с ( и закрываться с )

  • Должен быть один | в списке (то есть, по крайней мере, две альтернативы)

  • Любые другие случаи (я) ( или ) должны оставаться нетронутыми.

Обновление: мне также нужно иметь дело с несколькими парами кронштейнов, такими как:

  /var/(www|www2)/index.(htm|html|php|shtml) 

извините, я не сказал этого сразу.

Обновление 2: Если вы хотите сделать то, что я пытаюсь сделать в файловой системе, обратите внимание, что glob () уже выводит эту функциональность из коробки. Нет необходимости реализовывать пользовательский solutiom. См. Ниже приведенный ниже ответ Гордона.

Решение без регулярных выражений 🙂

 <?php $test = '/var/www/index.(htm|html|php|shtml)'; /** * * @param string $str "/var/www/index.(htm|html|php|shtml)" * @return array "/var/www/index.htm", "/var/www/index.php", etc */ function expand_bracket_pair($str) { // Only get the very last "(" and ignore all others. $bracketStartPos = strrpos($str, '('); $bracketEndPos = strrpos($str, ')'); // Split on ",". $exts = substr($str, $bracketStartPos, $bracketEndPos - $bracketStartPos); $exts = trim($exts, '()|'); $exts = explode('|', $exts); // List all possible file names. $names = array(); $prefix = substr($str, 0, $bracketStartPos); $affix = substr($str, $bracketEndPos + 1); foreach ($exts as $ext) { $names[] = "{$prefix}{$ext}{$affix}"; } return $names; } function expand_filenames($input) { $nbBrackets = substr_count($input, '('); // Start with the last pair. $sets = expand_bracket_pair($input); // Now work backwards and recurse for each generated filename set. for ($i = 0; $i < $nbBrackets; $i++) { foreach ($sets as $k => $set) { $sets = array_merge( $sets, expand_bracket_pair($set) ); } } // Clean up. foreach ($sets as $k => $set) { if (false !== strpos($set, '(')) { unset($sets[$k]); } } $sets = array_unique($sets); sort($sets); return $sets; } var_dump(expand_filenames('/(a|b)/var/(www|www2)/index.(htm|html|php|shtml)')); не <?php $test = '/var/www/index.(htm|html|php|shtml)'; /** * * @param string $str "/var/www/index.(htm|html|php|shtml)" * @return array "/var/www/index.htm", "/var/www/index.php", etc */ function expand_bracket_pair($str) { // Only get the very last "(" and ignore all others. $bracketStartPos = strrpos($str, '('); $bracketEndPos = strrpos($str, ')'); // Split on ",". $exts = substr($str, $bracketStartPos, $bracketEndPos - $bracketStartPos); $exts = trim($exts, '()|'); $exts = explode('|', $exts); // List all possible file names. $names = array(); $prefix = substr($str, 0, $bracketStartPos); $affix = substr($str, $bracketEndPos + 1); foreach ($exts as $ext) { $names[] = "{$prefix}{$ext}{$affix}"; } return $names; } function expand_filenames($input) { $nbBrackets = substr_count($input, '('); // Start with the last pair. $sets = expand_bracket_pair($input); // Now work backwards and recurse for each generated filename set. for ($i = 0; $i < $nbBrackets; $i++) { foreach ($sets as $k => $set) { $sets = array_merge( $sets, expand_bracket_pair($set) ); } } // Clean up. foreach ($sets as $k => $set) { if (false !== strpos($set, '(')) { unset($sets[$k]); } } $sets = array_unique($sets); sort($sets); return $sets; } var_dump(expand_filenames('/(a|b)/var/(www|www2)/index.(htm|html|php|shtml)')); 

Я думаю, вы ищете:

/ (([^ |] +) (| ([^ |] +)) +) /

В принципе, поставьте разделитель '|' в повторяющийся узор.

Кроме того, ваши слова должны быть составлены «не трубы», а не «не parens», с вашего третьего требования.

Кроме того, предпочитайте + для * для этой проблемы. + означает «по крайней мере один». * означает «ноль или больше».

Не совсем то, что вы просите, но что не так, просто принимая то, что вам нужно, чтобы получить список (игнорируя | s), помещая его в переменную, а затем explode на | s? Это дало бы вам массив из многих предметов, которые были (в том числе 1, если не было).

Может быть, я все еще не понимаю вопроса, но, по моему предположению, вы работаете через файловую систему, пока не нажмете один из файлов, и в этом случае вы могли бы сделать это

 $files = glob("$path/index.{htm,html,php,shtml}", GLOB_BRACE); 

Результирующий массив будет содержать любой файл, соответствующий вашим расширениям в $ path или none. Если вам нужно включить файлы по определенному заказу на добавочный номер, вы можете foreach через массив с упорядоченным списком расширений, например

 foreach(array('htm','html','php','shtml') as $ext) { foreach($files as $file) { if(pathinfo($file, PATHINFO_EXTENSION) === $ext) { // do something } } } 

Изменить: и да, вы можете иметь несколько фигурных скобок в glob.

Ответ дан, но это забавная головоломка, и я просто не мог сопротивляться

 function expand_filenames2($str) { $r = array($str); $n = 0; while(preg_match('~(.*?) \( ( \w+ \| [\w|]+ ) \) (.*) ~x', $r[$n++], $m)) { foreach(explode('|', $m[2]) as $e) $r[] = $m[1] . $e . $m[3]; } return array_slice($r, $n - 1); } print_r(expand_filenames2('/(a|b)/var/(ignore)/(www|www2)/index.(htm|html|php|shtml)!')); 

может быть, это немного объясняет, почему нам так нравятся регулярные выражения;)