我需要从完整文件路径中获取文件的名称。我试着使用:从完整路径获取文件名
$out_fname =~ s/[\/\w+\/]+//;
但它“吃掉”也文件名的purts。
例如:
一个文件: /bla/bla/folder/file.part.1.file
, 它返回: .part.1,file
我需要从完整文件路径中获取文件的名称。我试着使用:从完整路径获取文件名
$out_fname =~ s/[\/\w+\/]+//;
但它“吃掉”也文件名的purts。
例如:
一个文件: /bla/bla/folder/file.part.1.file
, 它返回: .part.1,file
我与其他的答案一致,只是想解释的错误在你的格局。正则表达式很棘手,但值得好好学习。
方括号定义了一组将匹配的对象。在你的情况下,它将匹配正斜杠,字符(来自\w
),+
字符或正斜杠字符(这是多余的)。然后你说要匹配1个或更多的那些。有多个可匹配的字符串。它会匹配最早的起始字符,所以第一个/
。然后它会尽可能地抓住。
这不是你想要的清楚。例如,如果您的某个目录名中有.
,则您将停在那里。 /blah.foo/bar/x.y.z
将返回.foo/bar/x.y.z
。
想想这个的方法是,你想匹配所有字符,包括最后的/
。
所有字符,然后斜线:/.*\//
但更安全,在前面加一个插入符号,以确保它从那里开始:/^.*\//
,并允许向前和反斜杠,使一个类为:/^.*[\/\\]/
(即elusive's answer)。
A 真的很好的参考是Learning Perl。大约有3个非常好的正则表达式章节。它们也适用于非Perl正则表达式用户。
这个怎么样:
$out_fname =~ s/^.*[\/\\]//;
应该删除你的文件名前的一切。
你可以这样做:
use File::Basename;
my $path = "/bla/bla/folder/file.part.1.file";
my $filename = basename($path);
不仅如此,它会使您的脚本在其他操作系统上移植。 – justintime 2010-11-11 12:30:27
这是正确的答案。 – 2010-11-11 12:50:36
是的,当有内置函数时不要使用正则表达式。正则表达式很昂贵,但有时你必须付钱。 – Keng 2010-11-11 13:30:46
除了File :: Basename之外,还有Path::Class,对于更复杂的操作,特别是在处理目录或跨平台/文件系统操作时,它可能非常方便。在这种情况下这可能是矫枉过正,但可能值得了解。
use Path::Class;
my $file = file("/bla/bla/folder/file.part.1.file");
my $filename = $file->basename;
在目录分隔符上使用split
是另一种选择。这与使用正则表达式(即使用文件名时,最好使用其他人已经考虑过边缘情况,可移植性,不同文件系统等的模块,因此不需要在后退和前进斜线上匹配),但作为另一种常用技术很有用你有一个重复分隔符的字符串。
my $file = "/bla/bla/folder/file.part.1.file";
my @parts = split /\//, $file;
my $filename = $parts[-1];
好主意!它最好的“分裂”......谢谢 – KingRider 2016-11-09 13:58:36
这是正是我会期待它在给定的替代保留。你说的是用最长的一串斜杠和单词字符替换掉。所以它抓住所有的字符,直到没有的第一个字符指定并删除它们。
它正在做你所要求的。我和其他人一起说使用File::Basename
来表达你想要做的事情。
但这里是做同样的事情的最快方法:
my $fname = substr($out_fname, rindex($out_fname, '/') + 1);
这里,说找到最后发生'/'
字符串中,并给我一个开始那个位置之后的文本。我从来没有反对过正则表达式,但它是你真正想做的事情的简单表达。我已经做了这么久的东西就是这样,我写了一个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);
}
我还需要从一堆路径名的拉刚刚过去的领域。这对我有效:
grep -o '/\([^/]*\)$' inputfile > outputfile
另一种方法是在字符串末尾处锚定,并在目录分隔符和字符串末尾匹配不是目录分隔符的所有内容(使用否定类,[^ ...]')例如'$ out_fname =〜m {[\/\\]([^ \/\\] +)$};我的$ filename_only = $ 1;' – plusplus 2010-11-11 14:26:50