我需要从完整路径字符串中提取直接子目录的名称。
例如,假设我们有:
$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”。等。
目前这就是我所拥有的,并且它有效(据我测试过)。我只是想知道是否有一种更简单的方法,因为我发现我使用了很多字符串函数。也许在一行中有一些神奇的正则表达式? (不幸的是,我对regexp并不太好。)
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;
}
正如你所看到的,为了处理一些奇怪的情况(输入中没有'/',空输入等),它有点hacky。我希望所有这些都是有道理的。欢迎任何帮助/建议。
更新(更改解决方案):
好吧 Alix Axel 让它发现了。这是他的解决方案,略微调整,以便它符合我的确切要求(例如:它必须返回一个字符串,只输出目录(而不是文件))
function getsubdir($str,$dir) {
$str = dirname($str);
$temp = array_slice(array_diff(explode('/', $str), explode('/', $dir)), 0, 1);
return $temp[0];
}
答案 0 :(得分:4)
你走了:
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);
}
答案 1 :(得分:2)
如何将整个事物分成数组:
$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];
我现在无法测试它,但它应该有效。
答案 2 :(得分:0)
这是一个类似的“短”解决方案,这次使用字符串函数而不是数组函数。如果没有从字符串中获取相应的部分,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)