Извлечь прямой подкаталог из строки пути - PullRequest
1 голос
/ 01 мая 2010

Мне нужно извлечь имя прямого подкаталога из строки полного пути.

Например, скажем, у нас есть:

$str = "dir1/dir2/dir3/dir4/filename.ext";
$dir = "dir1/dir2";

Тогда имя подкаталога в пути $ str относительно $ dir будет "dir3". Обратите внимание, что $ dir никогда не имеет '/' на концах.

Так что функция должна быть:

$subdir = getsubdir($str,$dir);
echo $subdir; // Outputs "dir3"

Если $ dir = "dir1", то результатом будет "dir2". Если $ dir = "dir1 / dir2 / dir3 / dir4", тогда вывод будет "" (пустой). Если $ dir = "", то результатом будет "dir1". Etc ..

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

function getsubdir($str,$dir) {
    // Remove the filename
    $str = dirname($str);

    // Remove the $dir
    if(!empty($dir)){
        $str = str_replace($dir,"",$str);
    }

    // Remove the leading '/' if there is one
    $si = stripos($str,"/");
    if($si == 0){
        $str = substr($str,1);
    }

    // Remove everything after the subdir (if there is anything)
    $lastpart = strchr($str,"/");
    $str = str_replace($lastpart,"",$str);

    return $str;
}

Как вы можете видеть, это немного странно для обработки некоторых нечетных случаев (без '/' на входе, пустого ввода и т. Д.). Я надеюсь, что все это имело смысл. Любая помощь / предложения приветствуются.

Обновление (измененное решение):

Ну Аликс Аксель на месте. Вот его решение с небольшими изменениями, чтобы оно соответствовало моим точным требованиям (например: оно должно возвращать строку, должны выводиться только каталоги (не файлы))

function getsubdir($str,$dir) {
    $str = dirname($str);
    $temp = array_slice(array_diff(explode('/', $str), explode('/', $dir)), 0, 1);
    return $temp[0];   
}

Ответы [ 3 ]

4 голосов
/ 01 мая 2010

Вот, пожалуйста:

function getSubDir($dir, $sub)
{
    return array_slice(array_diff(explode('/', $dir), explode('/', $sub)), 0, 1);
}

EDIT - Защита от взлома:

function getSubDirFoolproof($dir, $sub)
{
    /*
    This is the ONLY WAY we have to make SURE that the
    last segment of $dir is a file and not a directory.
    */
    if (is_file($dir))
    {
        $dir = dirname($dir);
    }

    // Is it necessary to convert to the fully expanded path?
    $dir = realpath($dir);
    $sub = realpath($sub);

    // Do we need to worry about Windows?
    $dir = str_replace('\\', '/', $dir);
    $sub = str_replace('\\', '/', $sub);

    // Here we filter leading, trailing and consecutive slashes.
    $dir = array_filter(explode('/', $dir));
    $sub = array_filter(explode('/', $sub));

    // All done!
    return array_slice(array_diff($dir, $sub), 0, 1);
}
2 голосов
/ 01 мая 2010

Как насчет разбить все это на массив:

$fullpath = explode("/", "dir1/dir2/dir3/dir4/filename.ext");
$fulldir  = explode("/", "dir1/dir2");

// Will result in array("dir1","dir2","dir3", "dir4", "filename.ext");
// and            array("dir1", "dir2");

тогда вы сможете использовать array_diff () :

$remainder = array_diff($fullpath, $fulldir);

// Should return array("dir3", "dir4", "filename.ext");

тогда получить прямого ребенка легко:

echo $remainder[0];

Я не могу проверить это сейчас, но это должно сработать.

0 голосов
/ 01 мая 2010

Вот аналогичное «короткое» решение, на этот раз с использованием строковых функций, а не функций массива. Если нет соответствующей части, которую нужно получить из строки, getsubdir вернет FALSE. Сегмент strtr - это быстрый способ избежать процентов, которые имеют особое значение для sscanf.

function getsubdir($str, $dir) {
    return sscanf($str, strtr($dir, '%', '%%').'/%[^/]', $name) === 1 ? $name : FALSE;
}

И быстрый тест, чтобы вы могли увидеть, как он ведет себя:

$str = "dir1/dir2/dir3/dir4/filename.ext";
var_dump(
    getSubDir($str, "dir1"),
    getSubDir($str, "dir1/dir2/dir3"),
    getSubDir($str, "cake")
);
// string(4) "dir2"
// string(4) "dir4"
// bool(false)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...