Regex 仅从完整路径获取文件名

Regex 仅从完整路径获取文件名,regex,perl,Regex,Perl,我需要从完整的文件路径中获取文件名。我尝试使用: $out\u fname=~s/[\/\w+\/] 但它也会“吃掉”文件名 例如: 对于文件: /bla/bla/folder/file.part.1.file, 它返回: .part.1,文件这个怎么样: $out_fname =~ s/^.*[\/\\]//; 它应该删除文件名前面的所有内容。您可以执行以下操作: use File::Basename; my $path = "/bla/bla/folder/file.part.1.fil

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

$out\u fname=~s/[\/\w+\/]

但它也会“吃掉”文件名

例如:

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

这个怎么样:

$out_fname =~ s/^.*[\/\\]//;
它应该删除文件名前面的所有内容。

您可以执行以下操作:

use File::Basename;

my $path = "/bla/bla/folder/file.part.1.file";
my $filename = basename($path);

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

方括号定义了一类将匹配的对象。在您的情况下,它将与正斜杠、单词字符(来自
\w
)、
+
字符或正斜杠字符匹配(这是多余的)。那么你是说要匹配其中的一个或多个。有多个字符串可以匹配。它将匹配最早的起始字符,因此第一个
/
。然后它将尽可能多地抓取

这显然不是你想要的。例如,如果您的一个目录名中有一个
,那么您就到此为止
/blah.foo/bar/x.y.z
将返回
.foo/bar/x.y.z

考虑到这一点,您需要匹配所有字符,包括最后的
/

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

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

要允许向前和向后斜杠,请为此创建一个类:
/^.[\/\\]/
(即)


一个非常好的参考是。大约有3个非常好的正则表达式章节。它们也适用于非Perl regex用户。

除了File::Basename之外,还有一个,它可以方便地进行更复杂的操作,特别是在处理目录或跨平台/文件系统操作时。在这种情况下,这可能是杀伤力过大,但可能值得了解

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];
这正是我希望它在给定的替换中保留的内容。您的意思是将最长的斜杠字符串和单词字符替换为零。所以它会抓取所有的字符,直到你没有指定的第一个字符,然后删除它们

它在做你要求它做的事情。我和其他人一起说,用你的努力去做

但下面是做同样事情的最快方法:

my $fname = substr( $out_fname, rindex( $out_fname, '/' ) + 1 );
这里,它说查找字符串中最后一个出现的
“/”
,并给出从该位置后面开始的文本。我并不反对正则表达式,但这是一个简单的表达你真正想做的事情。我已经做了这么长时间了,我在
sub之后写了一篇
last\u:

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

不仅如此,它将使您的脚本在其他操作系统上可移植。是的,当有内置函数时,不要使用正则表达式。regex很昂贵,但有时你得付钱。File::Basename在Core中(即随Perl一起提供),但我不认为这是“内置的”,只有
perldoc perlfunc
中的那些函数。另一种选择是在字符串的末尾锚定,并匹配所有不是目录分隔符的内容(使用否定类,
[^…]
),位于目录分隔符和字符串结尾之间,例如,
$out\u fname=~m{[\/\\]([^\/\]+)$;my$filename_only=$1