Почему мои регулярные выражения Perl правильно извлекают имя файла из пути? - PullRequest
2 голосов
/ 18 мая 2010

Я пытаюсь разобрать имя файла по путям. У меня есть это:

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

Может кто-нибудь указать, что я делаю не так?

Спасибо! :)

Ответы [ 4 ]

7 голосов
/ 18 мая 2010

В этом случае, как уже говорили другие, ошибка заключается в том, чтобы сделать это вручную.

В дополнение к 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";
4 голосов
/ 18 мая 2010

Почему бы не использовать File :: Basename ?

$name = basename($filepath)
print $name

Регулярное выражение

m/^.*\\(.*[.].*)$/
#    ^^

предполагает разделитель \, поэтому случаи 1 и 3 никогда не будут совпадать. В случае 2

"c:\\Windows\eric\filename.pdf";

\e и \f являются специальными символами в Perl. Таким образом, код «правильно» возвращает Windows\eric\filename.pdf в качестве имени файла. Не забудьте использовать \\!

3 голосов
/ 18 мая 2010

Perl предоставляет эту возможность: http://perldoc.perl.org/File/Basename.html

Вы также должны быть осторожны с побегами строк - ваша строка пути Windows экранируется на '\', '\ f' и '\ e' - уже давно, как я имел дело с экранированием Perl, но я Я предполагаю, что \ e также глотает 'r' после него. Это объясняет неожиданный вывод.

2 голосов
/ 18 мая 2010

Ну, ответ на то, что происходит, будет: различные ошибки.

my $filepath = "/Users/Eric/Documents/foldername/filename.pdf";
$filepath =~ m/^.*\\(.*[.].*)$/;
print "Linux path:";
print $1 . "\n\n";
print "-------\n";

$filepath не содержит \\ s, поэтому он не будет совпадать, и нет $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, более активны, чем строки в одинарных кавычках. Таким образом, вам нужно экранировать все ваши обратные слеши, как это:

my $filepath = "c:\\Windows\\eric\\filename.pdf";

или просто используйте одинарные кавычки:

my $filepath = 'c:\Windows\eric\filename.pdf';

На самом деле, поскольку Perl понимает '/' для Windows, это тоже работает (но не для регулярных выражений).

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...