我想要 Perl 相当于 Python 的 os.path.normpath()
:
Normalize a pathname by collapsing redundant separators and up-level references so that A//B, A/B/, A/./B and A/foo/../B all become A/B. This string manipulation may change the meaning of a path that contains symbolic links. […]
例如,我想转换
'/a/../b/./c//d'
进入 /b/c/d
.我正在操作的路径并不代表本地文件树中的真实目录。不涉及符号链接(symbolic link)。因此,简单的字符串操作可以正常工作。
我试过
Cwd::abs_path
和 File::Spec
,但他们不做我想做的事。my $path = '/a/../b/./c//d';
File::Spec->canonpath($path);
File::Spec->rel2abs($path, '/');
# Both return '/a/../b/c/d'.
# They don't remove '..' because it might change
# the meaning of the path in case of symlinks.
Cwd::abs_path($path);
# Returns undef.
# This checks for the path in the filesystem, which I don't want.
Cwd::fast_abs_path($path);
# Gives an error: No such file or directory
可能相关链接:
最佳答案
鉴于 File::Spec 几乎是我所需要的,我最终编写了一个删除 ../
的函数。来自 File::Spec->canonpath()
. The full code including tests is available as a GitHub Gist .
use File::Spec;
sub path_normalize_by_string_manipulation {
my $path = shift;
# canonpath does string manipulation, but does not remove "..".
my $ret = File::Spec->canonpath($path);
# Let's remove ".." by using a regex.
while ($ret =~ s{
(^|/) # Either the beginning of the string, or a slash, save as $1
( # Followed by one of these:
[^/]| # * Any one character (except slash, obviously)
[^./][^/]| # * Two characters where
[^/][^./]| # they are not ".."
[^/][^/][^/]+ # * Three or more characters
) # Followed by:
/\.\./ # "/", followed by "../"
}{$1}x
) {
# Repeat this substitution until not possible anymore.
}
# Re-adding the trailing slash, if needed.
if ($path =~ m!/$! && $ret !~ m!/$!) {
$ret .= '/';
}
return $ret;
}
关于perl - 如何规范化 Perl 中的路径? (不检查文件系统),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45631519/