代码之家  ›  专栏  ›  技术社区  ›  SIMEL

仅从完整路径获取文件名

  •  4
  • SIMEL  · 技术社区  · 14 年前

    我需要从完整的文件路径中获取文件名。我试过使用:

    $out_fname =~ s/[\/\w+\/]+//;

    但它也“吃掉”了文件名。

    例子:

    对于文件: /bla/bla/folder/file.part.1.file , 它返回: .part.1,file

    7 回复  |  直到 14 年前
        1
  •  4
  •   Community pid    7 年前

    我同意其他的答案,但只是想解释一下你模式中的错误。Regex很棘手,但值得好好学习。

    方括号定义一类将匹配的对象。在您的情况下,它将与正斜杠匹配,a 文字字符 (来自 \w ),和 + 字符或正斜杠字符(这是多余的)。然后你说要匹配其中的一个或多个。有多个字符串可以匹配。它将匹配最早的开始字符,因此第一个 / . 然后它会尽可能多的抓住。

    这不是你想要的。例如,如果你有一个 . 在你的一个目录名中,你会停在那里。 /blah.foo/bar/x.y.z 会回来的 .foo/bar/x.y.z .

    考虑这一点的方法是,你想匹配所有字符,包括最后一个 / .

    所有字符然后斜杠: /.*\//

    但是为了更安全,在前面添加一个插入符号以确保它从那里开始: /^.*\//

    并允许向前和向后斜杠,为此创建一个类: /^.*[\/\\]/ (即。 elusive's answer ).

    一个 真正地 好的参考是 Learning Perl . 有大约3个非常好的regex章节。它们也适用于非Perl regex用户。

        2
  •  16
  •   codaddict    14 年前

    你可以:

    use File::Basename;
    
    my $path = "/bla/bla/folder/file.part.1.file";
    my $filename = basename($path);
    
        3
  •  5
  •   plusplus    14 年前

    除了File::Basename,还有 Path::Class ,这对于更复杂的操作非常方便,特别是在处理目录或跨平台/文件系统操作时。在这种情况下可能是杀伤力过大,但可能值得了解。

    use Path::Class;
    
    my $file = file( "/bla/bla/folder/file.part.1.file" );
    my $filename = $file->basename;
    
        4
  •  1
  •   plusplus    14 年前

    使用 split 在目录分隔符上是另一种选择。这与使用regex有相同的注意事项(即,对于文件名,最好使用一个模块,在该模块中,其他人已经考虑过边缘情况、可移植性、不同的文件系统等,因此您不需要同时在反斜杠和正斜杠上进行匹配),但对于另一种具有重复分隔符的字符串的通用技术很有用。

    my $file = "/bla/bla/folder/file.part.1.file";
    my @parts = split /\//, $file;
    my $filename = $parts[-1];
    
        5
  •  1
  •   Axeman maxelost    14 年前

    这是 确切地 我所期望的 保持 在给定的替换中。你的意思是把最长的斜线和单词字符替换为空。所以它抓住所有的角色直到第一个角色 没有 指定并删除它们。

    它在做你要求它做的事。我和其他人一起说 File::Basename 为了你想做的事。

    但这里是做同样事情的最快方法:

    my $fname = substr( $out_fname, rindex( $out_fname, '/' ) + 1 );
    

    在这里,上面写着 最后的 发生 '/' 在字符串中,给我一个从那个位置开始的文本。我并不反对regex,但这只是你真正想做的事情的一个简单表达。我已经做了这么久了,我写了 last_after 附属的:

    sub last_after {
        my ( $string, $delim ) = @_;
        unless ( length( $string ) and my $ln = length( $delim )) {
            return $string // '';
        }
        my $ri = rindex( $string, $delim );
        return $ri == -1 ? $string : substr( $string, $ri + $ln );
    }
    
        6
  •  0
  •   chappjc    9 年前

    我还需要从一堆路径名中提取最后一个字段。这对我有效:

    grep -o '/\([^/]*\)$' inputfile > outputfile
    
        7
  •  -1
  •   jwueller    14 年前

    这个呢:

    $out_fname =~ s/^.*[\/\\]//;
    

    它应该删除文件名前面的所有内容。