如何用Perl提取含多圆点文件名的文件名与扩展名
解决Perl中含多圆点文件名的提取问题
嘿,我来帮你搞定这个多圆点文件名的提取问题!你的现有代码用split(/\./)会把所有圆点都作为分隔符,所以遇到文件名里带多个点的情况就卡壳了——我们真正需要的是以最后一个圆点为分界,前面的是文件名,后面的是扩展名,对吧?
方案1:用正则表达式精准分割
我们可以用正则只匹配最后一个圆点(也就是后面跟着扩展名的那个点),避免把文件名里的圆点误拆。这里有两种直观的写法:
写法A:带正向预查的split
修改循环里的分割逻辑,把全量拆分换成只拆分最后一个圆点:
my @fields = split(/\.(?=[^.]+$)/, $recordLine, 2);
- 正则
\.(?=[^.]+$)的作用:匹配一个圆点,同时要求这个圆点后面必须跟着「至少一个非圆点字符直到字符串结尾」(正向预查(?=...)不会消耗字符,只是做条件判断) - 最后加
, 2是限制最多分割成2部分,避免意外拆分
修改后的完整代码:
use strict; use warnings; print "Perl Starting ... \n\n"; open my $input_filehandle1, '<', 'test1.txt' or die "No input Filename Found test1.txt ... \n"; while (defined(my $recordLine = <$input_filehandle1>)) { chomp($recordLine); # 仅分割最后一个圆点 my @fields = split(/\.(?=[^.]+$)/, $recordLine, 2); # 兼容无扩展名的情况(按需保留) if (@fields == 2) { print "FileName: $fields[0] ... Ext: $fields[1] ... \n"; } else { print "FileName: $fields[0] ... Ext: (no extension) ... \n"; } }#end while-loop print "\nPerl End ... \n\n"; 1;
写法B:正则捕获分组
另一种更易读的方式是直接用正则捕获文件名和扩展名:
while (defined(my $recordLine = <$input_filehandle1>)) { chomp($recordLine); if ($recordLine =~ /^(.*)\.([^.]+)$/) { my $filename = $1; my $ext = $2; print "FileName: $filename ... Ext: $ext ... \n"; } else { print "FileName: $recordLine ... Ext: (no extension) ... \n"; } }
这个正则^(.*)\.([^.]+)$的逻辑:
(.*):捕获任意字符(尽可能多,直到最后一个圆点)作为文件名\.:匹配最后一个圆点([^.]+)$:捕获所有非圆点字符直到结尾作为扩展名
方案2:用Perl自带的File::Basename模块(更专业)
如果以后需要处理带路径的文件名,或者想更规范地解析文件名,推荐用Perl核心模块File::Basename——它专门为文件名处理设计,健壮性拉满:
修改后的代码:
use strict; use warnings; use File::Basename; # 引入核心模块 print "Perl Starting ... \n\n"; open my $input_filehandle1, '<', 'test1.txt' or die "No input Filename Found test1.txt ... \n"; while (defined(my $recordLine = <$input_filehandle1>)) { chomp($recordLine); # fileparse第二个参数是匹配扩展名的正则,这里匹配最后一个点及后续内容 my ($filename, $path, $ext) = fileparse($recordLine, qr/\.[^.]*/); # 去掉扩展名前面的圆点(如果需要带点的扩展名可以直接用$ext) my $clean_ext = substr($ext, 1); print "FileName: $filename ... Ext: $clean_ext ... \n"; }#end while-loop print "\nPerl End ... \n\n"; 1;
这个方法的优势在于,即使输入里包含完整路径(比如/data/docs/amazing c. document.docx),它也能正确提取文件名和扩展名,无需额外处理路径部分。
最终测试结果
不管用哪种方案,运行后都会得到你期望的输出:
Perl Starting ... FileName: test word document ... Ext: docx ... FileName: amazing c. document ... Ext: docx ... FileName: 1. 2. 3.45 document ... Ext: docx ... Perl End ...
内容的提问来源于stack exchange,提问作者Sam B
相关产品推荐
相关产品推荐

