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";

c/d を印刷したい (つまり、ディレクトリ/ファイル名のリスト)。上記はそれを行うための最良の方法ですか?上記は明らかに機能しますが、私はどういうわけかそれが好きではありません。それを行うためのより良い/クールな/効率的な方法はありますか? 正規表現の一致のようなもの??

実際、そのプログラムは、私が本当にやりたいことの一部を実行するだけです。これらはさまざまなユースケースであり、期待される結果は次のとおりです。

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。ドル記号($)は、一致を文字列の末尾に固定するように強制するため、右側または。に一致し$zます。存在する場合はそこに一致することを許可します{0,1}が、存在しない場合は無視します。これらは/dとのd場合に必要です。

可能なすべてのパスのデモ

#!/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 に答える