Получение только имени файла из полного пути - PullRequest
4 голосов
/ 11 ноября 2010

Мне нужно получить из полного пути к файлу только имя файла. Я пытался использовать:

$out_fname =~ s/[\/\w+\/]+//;

но он "съедает" и портит имя файла.

пример:

для файла: /bla/bla/folder/file.part.1.file, он вернулся: .part.1,file

Ответы [ 7 ]

16 голосов
/ 11 ноября 2010

Вы можете сделать:

use File::Basename;

my $path = "/bla/bla/folder/file.part.1.file";
my $filename = basename($path);
5 голосов
/ 11 ноября 2010

Помимо File :: Basename, есть также Path :: Class , который может быть полезен для более сложных операций, особенно при работе с каталогами или операциями между платформами и файловой системой.В этом случае это, вероятно, излишне, но, возможно, стоит знать об этом.

use Path::Class;

my $file = file( "/bla/bla/folder/file.part.1.file" );
my $filename = $file->basename;
4 голосов
/ 11 ноября 2010

Я согласен с другими ответами, но просто хотел объяснить ошибку в вашей схеме. Regex сложно, но стоит хорошо учиться.

Квадратные скобки определяют класс объектов, которые будут соответствовать. В вашем случае он будет совпадать с косой чертой, символом слова (из \w), символом + или знаком косой черты (это избыточно). Тогда вы говорите, чтобы соответствовать 1 или более из них. Есть несколько строк, которые могут совпадать. Он будет соответствовать самому раннему начальному символу, поэтому первый /. Тогда он будет хватать как можно больше.

Это не то, что вы намеревались ясно. Например, если у вас есть . в одном из имен каталогов, вы остановитесь на этом. /blah.foo/bar/x.y.z вернет .foo/bar/x.y.z.

Способ думать так: вы хотите сопоставить все символы вплоть до финального /.

Все символы после косой черты: /.*\//

Но для большей безопасности добавьте каретку спереди, чтобы убедиться, что она начинается там: /^.*\//

И чтобы разрешить прямую и обратную косую черту, создайте для этого класс: /^.*[\/\\]/ (т.е. неуловимый ответ ).

A действительно хороший справочник - Learning Perl . Есть около 3 действительно хороших глав регулярных выражений. Они также применимы к пользователям не-Perl регулярных выражений.

1 голос
/ 11 ноября 2010

Это точно , что, как я ожидаю, сохранит в данной замене. Вы говорите, заменить самую длинную строку слешей и символов слова ничем. Таким образом, он захватывает все символы до тех пор, пока первый символ, который вы не * указали, и удаляет их.

Он делает то, что вы просите. Я присоединяюсь к другим и говорю, что используйте File::Basename для того, что вы пытаетесь сделать.

Но вот самый быстрый способ сделать то же самое:

my $fname = substr( $out_fname, rindex( $out_fname, '/' ) + 1 );

Здесь говорится, что найдите в строке last вхождение '/' и дайте мне текст, начинающийся после этой позиции. Я не против регулярных выражений, но это простое выражение того, что вы действительно хотите сделать. Мне так долго приходилось делать подобные вещи, я написал подпункт 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 );
}
1 голос
/ 11 ноября 2010

Использование split в качестве разделителя каталогов является еще одной альтернативой.Это имеет те же предостережения, что и при использовании регулярных выражений (т. Е. С именами файлов лучше использовать модуль, в котором кто-то другой уже задумывался о крайних случаях, переносимости, различных файловых системах и т. Д., И поэтому вам не нужно сопоставлять как в обратном, так и в обратном направлении).-блики), но полезен в качестве еще одного общего метода, где у вас есть строка с повторяющимся разделителем.

my $file = "/bla/bla/folder/file.part.1.file";
my @parts = split /\//, $file;
my $filename = $parts[-1];
0 голосов
/ 03 марта 2015

Мне также нужно было извлечь только последнее поле из набора путей.Это сработало для меня:

grep -o '/\([^/]*\)$' inputfile > outputfile
0 голосов
/ 11 ноября 2010

Что по этому поводу:

$out_fname =~ s/^.*[\/\\]//;

Это должно удалить все перед вашим именем файла.

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