我试图从路径解析文件名。我有这个:
my $filepath = "/Users/Eric/Documents/foldername/filename.pdf";
$filepath =~ m/^.*\\(.*[.].*)$/;
print "Linux path:";
print $1 . "\n\n";
print "-------\n";
my $filepath = "c:\\Windows\eric\filename.pdf";
$filepath =~ m/^.*\\(.*[.].*)$/;
print "Windows path:";
print $1 . "\n\n";
print "-------\n";
my $filepath = "filename.pdf";
$filepath =~ m/^.*\\(.*[.].*)$/;
print "Without path:";
print $1 . "\n\n";
print "-------\n";
但是回归:
Linux path:
-------
Windows path:Windowsic
ilename.pdf
-------
Without path:Windowsic
ilename.pdf
-------
我期待着这个:
Linux path:
filename.pdf
-------
Windows path:
filename.pdf
-------
Without path:
filename.pdf
-------
有人可以指出我做错了吗?
谢谢! :)
答案 0 :(得分:7)
在这种情况下,正如其他人所说,错误就是手工完成。
除File::Basename
外,您还应该查看File::Spec
和Path::Class
。它们提供经过充分测试的跨平台方法来处理文件和目录。 Path::Class
特别提供了帮助方法来处理脚本所在系统的外来文件和目录名。看起来这可能会派上用场。
#!/usr/bin/env perl
use strict;
use warnings;
use Path::Class qw/file foreign_file/;
my $nix = "/Users/Eric/Documents/foldername/filename.pdf";
my $win = 'c:\\Windows\eric\filename.pdf'; # single quote to avoid escape issues
print file($nix)->basename(), "\n";
print foreign_file('Win32', $win)->basename(), "\n";
答案 1 :(得分:4)
为什么不使用File::Basename?
$name = basename($filepath)
print $name
正则表达式
m/^.*\\(.*[.].*)$/
# ^^
假定分隔符\
,因此情况1和3永远不会匹配。在案例2中,
"c:\\Windows\eric\filename.pdf";
\e
和\f
都是Perl中的特殊字符。所以代码“正确”返回Windows\eric\filename.pdf
作为文件名。请记住使用\\
!
答案 2 :(得分:3)
Perl提供此功能: http://perldoc.perl.org/File/Basename.html
你还需要警惕字符串转义 - 你的Windows路径字符串在'\','\ f'和'\ e'上被转义 - 自从我处理Perl转义以来已经有一段时间了,但是我猜测\ e也在吞下'r'之后。这解释了意外的输出。
答案 3 :(得分:2)
嗯,正在发生的事情的答案是:各种错误。
my $filepath = "/Users/Eric/Documents/foldername/filename.pdf";
$filepath =~ m/^.*\\(.*[.].*)$/;
print "Linux path:";
print $1 . "\n\n";
print "-------\n";
$filepath
中没有\\
个,因此它不匹配且没有$1
。你把/
放进去了。你的表达必须是:
# regular expression matches return their captures in a list context.
my ( $path ) = $filepath =~ m|/([^/.]*\.[^/.]*)$|;
print "Linux path:$path\n\n-------\n"; # little need to . a " string
my $filepath = "c:\\Windows\eric\filename.pdf";
$filepath =~ m/^.*\\(.*[.].*)$/;
print "Windows path:";
print $1 . "\n\n";
print "-------\n";
你正在使用双引号,它从UNIX shell中获得提示,比单引号字符串更活跃。因此,您需要转义所有反斜杠,如下所示:
my $filepath = "c:\\Windows\\eric\\filename.pdf";
或只使用单引号:
my $filepath = 'c:\Windows\eric\filename.pdf';
实际上,由于perl了解'/'
的窗口,这也适用(但不适用于正则表达式。)
my $filepath = "c:/Windows/eric/filename.pdf";
只要您在将其交还给Windows之前修复它。
my $filepath = "filename.pdf";
$filepath =~ m/^.*\\(.*[.].*)$/;
print "Without path:";
print $1 . "\n\n";
print "-------\n";
这不是匹配,因此$1
仍然是最后一场比赛。这就是重复的原因。但这指出了捕获捕获的价值而不是引用$1
。