perl - 如何规范化 Perl 中的路径? (不检查文件系统)

标签 perl path filepath

我想要 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

可能相关链接:
  • Normalized directory paths - perlmonks : 人们讨论了几种方法。
  • 最佳答案

    鉴于 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/

    相关文章:

    regex - 如何从 Perl 中的字符串中删除最后一个逗号

    Perl:如何打印 WWW::Curl::Form 内容?

    linux - 可执行文件可以动态解析其在文件系统上的位置或其实际的 "resting place"与用户的工作目录吗?

    javascript - 使用 nodejs 路径模块返回目录

    html - 我将与 ng-include 一起使用什么文件路径?

    unit-testing - perl 测试模拟 make_path

    perl - 当我模块化代码时开始发生 "Not an ARRAY reference"错误

    linux - 如何从命令行中的相对路径获取绝对路径

    apache - PHP : Include path that works both on Dev and Live

    linux - 如何评估 bash shell 中的给定路径