我需要從完整文件路徑中獲取文件的名稱。我試着使用:從完整路徑獲取文件名
$out_fname =~ s/[\/\w+\/]+//;
但它「吃掉」也文件名的purts。
例如:
一個文件: /bla/bla/folder/file.part.1.file
, 它返回: .part.1,file
我需要從完整文件路徑中獲取文件的名稱。我試着使用:從完整路徑獲取文件名
$out_fname =~ s/[\/\w+\/]+//;
但它「吃掉」也文件名的purts。
例如:
一個文件: /bla/bla/folder/file.part.1.file
, 它返回: .part.1,file
我與其他的答案一致,只是想解釋的錯誤在你的格局。正則表達式很棘手,但值得好好學習。
方括號定義了一組將匹配的對象。在你的情況下,它將匹配正斜槓,字符(來自\w
),+
字符或正斜槓字符(這是多餘的)。然後你說要匹配1個或更多的那些。有多個可匹配的字符串。它會匹配最早的起始字符,所以第一個/
。然後它會盡可能地抓住。
這不是你想要的清楚。例如,如果您的某個目錄名中有.
,則您將停在那裏。 /blah.foo/bar/x.y.z
將返回.foo/bar/x.y.z
。
想想這個的方法是,你想匹配所有字符,包括最後的/
。
所有字符,然後斜線:/.*\//
但更安全,在前面加一個插入符號,以確保它從那裏開始:/^.*\//
,並允許向前和反斜槓,使一個類爲:/^.*[\/\\]/
(即elusive's answer)。
A 真的很好的參考是Learning Perl。大約有3個非常好的正則表達式章節。它們也適用於非Perl正則表達式用戶。
這個怎麼樣:
$out_fname =~ s/^.*[\/\\]//;
應該刪除你的文件名前的一切。
你可以這樣做:
use File::Basename;
my $path = "/bla/bla/folder/file.part.1.file";
my $filename = basename($path);
不僅如此,它會使您的腳本在其他操作系統上移植。 – justintime 2010-11-11 12:30:27
這是正確的答案。 – 2010-11-11 12:50:36
是的,當有內置函數時不要使用正則表達式。正則表達式很昂貴,但有時你必須付錢。 – Keng 2010-11-11 13:30:46
除了File :: Basename之外,還有Path::Class,對於更復雜的操作,特別是在處理目錄或跨平臺/文件系統操作時,它可能非常方便。在這種情況下這可能是矯枉過正,但可能值得了解。
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];
好主意!它最好的「分裂」......謝謝 – KingRider 2016-11-09 13:58:36
這是正是我會期待它在給定的替代保留。你說的是用最長的一串斜槓和單詞字符替換掉。所以它抓住所有的字符,直到沒有的第一個字符指定並刪除它們。
它正在做你所要求的。我和其他人一起說使用File::Basename
來表達你想要做的事情。
但這裏是做同樣的事情的最快方法:
my $fname = substr($out_fname, rindex($out_fname, '/') + 1);
這裏,說找到最後發生'/'
字符串中,並給我一個開始那個位置之後的文本。我從來沒有反對過正則表達式,但它是你真正想做的事情的簡單表達。我已經做了這麼久的東西就是這樣,我寫了一個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);
}
我還需要從一堆路徑名的拉剛剛過去的領域。這對我有效:
grep -o '/\([^/]*\)$' inputfile > outputfile
另一種方法是在字符串末尾處錨定,並在目錄分隔符和字符串末尾匹配不是目錄分隔符的所有內容(使用否定類,[^ ...]')例如'$ out_fname =〜m {[\/\\]([^ \/\\] +)$};我的$ filename_only = $ 1;' – plusplus 2010-11-11 14:26:50