我不反对正则表达式,但我会这样做:
function simplify_path($path, $directory_separator = "/", $equivalent = true){
$path = trim($path);
// if it's absolute, it stays absolute:
$prepend = (substr($path,0,1) == $directory_separator)?$directory_separator:"";
$path_array = explode($directory_separator, $path);
if($prepend) array_shift($path_array);
$output = array();
foreach($path_array as $val){
if($val != '..' || ((empty($output) || $last == '..') && $equivalent)) {
if($val != '' && $val != '.'){
array_push($output, $val);
$last = $val;
}
} elseif(!empty($output)) {
array_pop($output);
}
}
return $prepend.implode($directory_separator,$output);
}
测试:
echo(simplify_path("../../../one/no/no/../../two/no/../three"));
// => ../../../one/two/three
echo(simplify_path("/../../one/no/no/../../two/no/../three"));
// => /../../one/two/three
echo(simplify_path("/one/no/no/../../two/no/../three"));
// => /one/two/three
echo(simplify_path(".././../../one/././no/./no/../../two/no/../three"));
// => ../../../one/two/three
echo(simplify_path(".././..///../one/.///./no/./no/../../two/no/../three/"));
// => ../../../one/two/three
我认为返回一个等效的字符串会更好,所以我尊重字符串开头出现的..。
如果你不想要它们,你可以用第三个参数 $equivalent = false 来调用它:
echo(simplify_path("../../../one/no/no/../../two/no/../three", "/", false));
// => one/two/three
echo(simplify_path("/../../one/no/no/../../two/no/../three", "/", false));
// => /one/two/three
echo(simplify_path("/one/no/no/../../two/no/../three", "/", false));
// => /one/two/three
echo(simplify_path(".././../../one/././no/./no/../../two/no/../three", "/", false));
// => one/two/three
echo(simplify_path(".././..///../one/.///./no/./no/../../two/no/../three/", "/", false));
// => one/two/three