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代码>