1
use File::Basename;
my $path = "a/b/c/d";
my $dirpath = basename ($path);
my $basepath = dirname ($path);
my $base_basepath = dirname ($basepath);
my $dir_dirpath = basename ($basepath);
print "$dir_dirpath/$dirpath\n";

I want c/d to be printed (i.e the list dir/filename). Is the above the best way to do that? The above obviously works but I somehow don't like it. Is there a better/cool/efficient way to do it? Something like a regex match??

Actually, that program just does a part of what I really want it to do. These are the different use cases and what the expected result is :

a/b/c/d => c/d d
b/c/d => c/d d
/c/d => c/d d
c/d => c/d d
/d => d
d => d
4

2 回答 2

2

File::Spec模块是操作文件路径的规范且可移植的方式,并 File::Spec::Functions允许直接访问该模块的功能,而不必在File::Spec->任何地方都为它们加上前缀。

use strict;
use warnings;

use File::Spec::Functions qw/ splitdir catdir /;

my $path = "a/b/c/d";
my @path = splitdir $path;
print catdir @path[-2,-1];

输出

c/d
于 2013-02-10T14:52:17.437 回答
1

使用拆分的一种方法

#!/usr/bin/perl

my $z="a/b/c/d";
my ($a, $b, $c, $d) = split ('/', $z);
print "$c/$d";

仅使用正则表达式

#!/usr/bin/perl

my $z = "a/b/c/d"; 
($a, $b) = $z[$cnt] =~ m#(\w+){0,1}/{0,1}(\w+)$#;
printf "$a/$b - $b\n";

注意:此方法查找尾随 dir1/dir2 并将它们保存到$a$b. 美元符号 ($) 强制匹配锚定到字符串的末尾,因此它匹配右侧 or $z。如果{0,1}它存在,则允许我们在那里匹配某些东西,但如果不存在则忽略它。这些对于/dd情况是必要的。

所有可能的路径演示

#!/usr/bin/perl

my @z = qw(a/b/c/d b/c/d /c/d c/d);

for (my $cnt = 0; $cnt <= 3; $cnt++) {
  ($a, $b) = $z[$cnt] =~ m#(\w+){0,1}/{0,1}(\w+)$#;
  printf "%10s   -   %s/%s  -  %s\n", $z[$cnt], $a, $b, $b;
}

### output
% ./script.pl 
a/b/c/d   -   c/d  -  d
  b/c/d   -   c/d  -  d
   /c/d   -   c/d  -  d
    c/d   -   c/d  -  d
     /d   -   /d  -  d
      d   -   /d  -  d

这只是表明这种方法适用于问题中提到的目录。

注意:这种方法确实有它的缺点。它仅适用于 UNIX 系统,需要特别注意目录名称的(\w+)匹配器。如果您的目录中有空格,这将失败。

于 2013-02-10T14:19:27.503 回答