在perl的条件下匹配文件名

时间:2013-12-23 08:49:43

标签: perl

我的文件包含lin.txt和lin1.txt等文件名以及其他.txt文件。我只需找到这些文件并仅打印一个文件。我有下面的代码,但它不知道匹配以lin *开头的文件。有什么问题?

$te_dir= "/projects/xxx/";
opendir (DIR, $te_dir) or die $!;
while (my $file = readdir(DIR))
{
                if ($file=~/\.txt/)
                {
            #// Doing some tasks.

            if($file ~= 'lin*.txt')
            {
              $linfile=$te_dir/$file;
              open(LINFILE, $linfile) or die "Couldn't open file $file:$!";
              while(my $line = <LINFILE>)
              {
                print $line;
              }
              close LINFILE;    

            }

        }

}

4 个答案:

答案 0 :(得分:3)

您正在将globs(shell通配符)与正则表达式混合使用。这是两种不同的形式,具有不同的语法和语义。在正则表达式中(这是Perl匹配使用的),n*匹配零个或多个字符n。你可能意味着

if ($file =~ /lin.*\.txt/)

还要注意运算符中的语法错误。您在第一个条件中正确拥有=~,但是您将其拼错为~=,您可以在此进行比较。 (也许这只是一个转录错误;对我来说,这会产生一个明确的语法错误,所以脚本不会首先运行。)

如@brianadams的回答所述,正确的正则表达式是

if ($file =~ /^lin.*\.txt$/)

^的开头和行$行的结尾以阻止例如来自匹配的feline.txt.html。 Perl正则表达式的默认行为是在输入字符串中的任何位置找到匹配项。

答案 1 :(得分:1)

匹配以lin

开头的文件
if ( $file =~ /^lin.*\.txt$/ )

答案 2 :(得分:1)

这是对代码的快速(和最小)重写可能会有所帮助:

use strict;
use warnings;

my $te_dir = "/projects/xxx/";
opendir( my $dirh, $te_dir ) or die "Could not open '$te_dir': $!";

while ( my $file = readdir($dirh) ) {
    next unless $file =~ /\.txt$/;

    #// Doing some tasks.
    if ( $file =~ /^ lin \d* \.txt $/x ) {
        my $linfile = "$te_dir/$file";
        open( my $fh, $linfile ) or die "Couldn't open file $linfile: $!";
        while ( my $line = <$fh> ) {
            print $line;
        }
        close $fh or die "Could not close $linfile: $!";
    }
}

首先,请注意我们已将strictwarnings放在代码的顶部。这将告诉你各种有趣的问题,包括拼写错误的变量名称。

接下来,我们切换到词汇句柄(例如,my $dirh而不是DIR)。您正在使用的句柄的“裸字”版本(DIRLINFILE已经被劝阻了很长一段时间,因为这些是有效的全局构造,并且通常全局数据很糟糕,因为当它被破坏时,它是很难说是什么打破了它,所以我们更喜欢词汇版本(用my内置声明的句柄。)

此外,这条线你可能没有按照你的想法行事:

$linfile=$te_dir/$file;

你试图用正斜杠粉碎目录和文件名,但由于你没有使用字符串插值,你实际上是在使用 division 。在这个数字上下文中,你的导演和文件名都可能会评估为零,当你试图打开一个文件时,会给你一个除零错误!

但是,如果您愿意使用CPAN模块,则可以更轻松地实现这一目标:

use strict;
use warnings;

use File::Find::Rule;
my $te_dir = "/projects/xxx/";
my @files  = File::Find::Rule->file->name('lin*.txt')->in($te_dir);

foreach my $linfile (@files) {

    #// Doing some tasks.
    open my $fh, $linfile or die "Couldn't open file $linfile: $!";                                                                                                      
    while ( my $line = <$fh> ) {
        print $line;
    }
}

没有麻烦,没有大惊小怪。在第一遍中只获取您想要的文件,并且已经拥有正确的文件名(请注意,我没有关闭文件句柄,因为当$fh超出{{1}末尾的范围时,它会自动关闭循环。)

答案 3 :(得分:0)

尝试从此处更改第二个if条件,

if($file ~= 'lin*.txt')

到此,

if($file =~ /lin*\.txt/)

您也可以尝试:if($file =~ /^lin*\.txt/),正如其他答案中已经指出的那样,但您需要确保$file变量中存储的文件名只包含文件名而不是整个路径。