从路径字符串中提取直接子目录

发布于 2024-08-30 13:47:07 字数 1413 浏览 1 评论 0原文

我需要从完整路径字符串中提取直接子目录的名称。

例如,假设我们有:

$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”。等等..

目前这就是我所拥有的,并且它有效(据我测试过)。我只是想知道是否有更简单的方法,因为我发现我使用了很多字符串函数。也许有一些神奇的正则表达式可以在一行中完成此操作? (不幸的是,我不太擅长正则表达式)。

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;
}

正如您所看到的,为了处理一些奇怪的情况(输入中没有“/”、输入为空等),它有点棘手。我希望这一切都是有道理的。欢迎任何帮助/建议。

更新(改变解决方案):

嗯,Alix Axel说得对。这是他的解决方案,稍作调整,使其符合我的确切要求(例如:它必须返回一个字符串,只应输出目录(而不是文件))

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

I need to extract the name of the direct sub directory from a full path string.

For example, say we have:

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

Then the name of the sub-directory in the $str path relative to $dir would be "dir3". Note that $dir never has '/' at the ends.

So the function should be:

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

If $dir="dir1" then the output would be "dir2". If $dir="dir1/dir2/dir3/dir4" then the output would be "" (empty). If $dir="" then the output would be "dir1". Etc..

Currently this is what I have, and it works (as far as I've tested it). I'm just wondering if there's a simpler way since I find I'm using a lot of string functions. Maybe there's some magic regexp to do this in one line? (I'm not too good with regexp unfortunately).

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;
}

As you can see, it's a little hacky in order to handle some odd cases (no '/' in input, empty input, etc). I hope all that made sense. Any help/suggestions are welcome.

Update (altered solution):

Well Alix Axel had it spot on. Here's his solution with slight tweaks so that it matches my exact requirements (eg: it must return a string, only directories should be outputted (not files))

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

ぺ禁宫浮华殁 2024-09-06 13:47:07

给你:

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

编辑 - 万无一失的实施:

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);
}

Here you go:

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

EDIT - Foolproof implementation:

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);
}
荒芜了季节 2024-09-06 13:47:07

如何将整个内容拆分为一个数组:

$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];

我现在无法测试它,但它应该可以工作。

How about splitting the whole thing into an array:

$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");

you should then be able to use array_diff():

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

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

then, getting the direct child is easy:

echo $remainder[0];

I can't test this right now but it should work.

软的没边 2024-09-06 13:47:07

这是一个类似的“短”解决方案,这次使用字符串函数而不是数组函数。如果没有从字符串中获取相应的部分,getsubdir将返回FALSEstrtr 段是转义百分比的快速方法,这对 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)

Here's a similar "short" solution, this time using string functions rather than array functions. If there is no corresponding part to be gotten from the string, getsubdir will return FALSE. The strtr segment is a quick way to escape the percents, which have special meaning to sscanf.

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

And a quick test so you can see how it behaves:

$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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文