【问题标题】:How can I extract a filename from a path using Perl?如何使用Perl从路径中提取文件名?
【发布时间】:2011-06-13 15:26:15
【问题描述】:

我有一个从数据库中填充的 Perl 变量。它的名字是$path。我需要得到另一个变量$file,它只有路径名中的文件名。

我试过了:

$file = $path =~ s/.*\///;

我对 Perl 很陌生。

【问题讨论】:

    标签: regex perl string operator-precedence


    【解决方案1】:

    为什么要重新发明轮子?使用File::Basename 模块:

    use File::Basename;
    ...
    $file = basename($path);
    

    为什么$file=$path=~s/.*\///; 不起作用?

    =~precedence 高于 =

    所以

    $file = $path =~s/.*\///;
    

    被视为:

    $file = ($path =~s/.*\///);
    

    $path 中进行替换并分配1(如果发生替换)或''(如果没有发生替换)。

    你想要的是:

    ($file = $path) =~s/.*\///;
    

    $path 的值分配给$file,然后在$path 中进行替换。

    但同样,这个解决方案也有很多问题:

    1. 这是不正确的。基于 Unix 的系统(不确定 Windows)中的文件名可以包含换行符。但是. 默认不匹配换行符。因此,您必须使用 s 修饰符,以便 . 也匹配换行符:

      ($file = $path) =~s/.*\///s;
      
    2. 1234563因此,请使用该模块,让它为您处理所有这些问题。

    【讨论】:

    • 同意。通常使用这样的模块比使用正则表达式更好,因为它是跨平台的。
    • 还要注意 File::Basename 是一个核心模块,并且一直在 Perl 5 中所以不需要安装。
    • 关于 File::Basename 的手册页,建议使用 fileparse 方法来完成此任务,因为“[basename] 并不总是像您期望的那样返回路径的文件名部分”
    【解决方案2】:
    use File::Basename 
    

    查看以下链接,了解其工作原理的详细说明:

    http://p3rl.org/File::Basename

    【讨论】:

      【解决方案3】:

      Path::Class 一开始可能看起来有点矫枉过正——制作文件和目录路径的对象——但它确实可以在复杂的脚本中得到回报,并提供许多好处,当你因范围蔓延而陷入困境时,它可以防止意大利面。 File::Spec 在第一个示例中用于解析路径的乐趣。

      use warnings;
      use strict;
      use Path::Class qw( file );
      use File::Spec;
      
      # Get the name of the current script with the procedural interface-
      my $self_file = file( File::Spec->rel2abs(__FILE__) );
      print
          " Full path: $self_file", $/,
          "Parent dir: ", $self_file->parent, $/,
          " Just name: ", $self_file->basename, $/;
      
      # OO                                    
      my $other = Path::Class::File->new("/tmp/some.weird/path-.unk#");
      print "Other file: ", $other->basename, $/;
      

      【讨论】:

        【解决方案4】:
        $url=~/\/([^\/]+)$/;
        print "Filename $1\n";
        

        【讨论】:

        • 为了获得更好的帖子,您可以扩展您的答案,解释为什么该特定正则表达式适用于各种示例。这将有助于您的答案对原始发帖人以及许多其他未来的读者有意义。
        【解决方案5】:

        我认为最好的方法是 -

        use File::Basename;
        
        my $file_name = basename($0);
        

        因此变量$file_name 将具有您的脚本的名称

        【讨论】:

          【解决方案6】:

          从路径中提取文件名对于 Unix 和 Windows 文件系统都非常容易,无需任何包:

          my $path;
          $path = 'C:\A\BB\C\windows_fs.txt';     # Windows
          #$path = '/a/bb/ccc/ddd/unix_fs.txt';    # Unix
          
          my $file =  (split( /\/|\\/, $path))[-1];
          print "File: $file\n";
          
          # variable $file is "windows_fs.txt"  for Windows
          # variable $file is "unix_fs.txt"     for Unix
          

          逻辑很简单:创建一个包含所有元素的数组来创建路径并检索最后一个。 Perl 允许使用从数组末尾开始的负索引。索引“-1”对应于最后一个元素。

          【讨论】:

          • 但是 File::Basename 存在于标准 Perl 库中,所以没有充分的理由不使用它。
          • 我曾遇到过需要执行 Perl 脚本但只有 perl.exe 可用的情况。你的方法行不通,而我的方法永远有效。
          • 如果安装了 Perl,那么标准 Perl 库也将可用。如果不是,您的 Perl 安装已损坏,您不应该将它用于任何事情。
          【解决方案7】:

          就这么简单:

          $path =~ /.*[\/\\](.*)/;    # will return 1 (or 0) and set $1
          my $file = $1;              # $1 contains the filename
          

          要检查文件名是否可用,请使用:

          $file = $1 if $path =~ /.*[\/\\](.*)/;
          

          图案:

          .*[\/\\](.*)
          | |     |
          | |     \- at last there is a group with the filename
          | \------- it's the last / in linux or the last \ in windows
          \--------- .* is very greedy, so it takes all it could
          

          Use e.g. https://regex101.com/ to check regular expressions.

          【讨论】:

            猜你喜欢
            • 2011-04-28
            • 1970-01-01
            • 1970-01-01
            • 2010-10-01
            • 2016-06-19
            • 1970-01-01
            • 1970-01-01
            • 2013-08-19
            相关资源
            最近更新 更多