如何在Perl中检查具有两个不同扩展名的文件

时间:2011-12-09 05:04:48

标签: perl

我有一个文件reflog,内容如下。将有具有相同名称但不同扩展名的项目。我想检查每个项目(例如file1file2file3),它需要存在于两个扩展中(.abc和{ {1}})。如果两个扩展都存在,它将执行一些正则表达式并打印输出。否则它只会报告文件名和扩展名(即,如果只存在file1.abc或file1.def,它将被打印出来。)

引用日志:

.def

我的脚本如下(从yb007脚本编辑),但我输出的一些问题我不知道如何解决。我注意到当reflog文件具有名为* abc.def的任何文件时(例如,即file8abc.def& file9abc.def),输出将会出错。它将减去最后4个后缀并返回错误的.ext(这里是.abc,但我想它应该是.def)。

file1.abc


file2.abc

file2.def 

file3.abc
file3.def

file4.abc 

file5.abc 
file5.def
file6.def
file8abc.def
file7.abc

file1.def
file9abc.def
file10def.abc

我的输出是这样的,这是错误的: -     1st: - 打印屏幕输出如下:                 结合所有: -          file.abc file.abc file1 file10def.abc file2 file3 file4.abc file5 file6.def file7.abc

    #! /usr/bin/perl 
    use strict; 
    use warnings; 
    my @files_abc ;
    my @files_def ;
    my $line;
    open(FILE1, 'reflog') || die ("Could not open reflog") ;
    open (FILE2, '>log') || die ("Could not open log") ;
    while ($line = <FILE1>) {   
        if($line=~ /(.*).abc/) {       
            push(@files_abc,$1);   
        } elsif ($line=~ /(.*).def/) { 
            push(@files_def,$1);     } 
    } 
    close(FILE1);

    my %first = map { $_ => 1 } @files_def ;
    my @same = grep { $first{$_} } @files_abc ;
    my @abc_only = grep { !$first{$_} } @files_abc ;
    foreach my $abc (sort @abc_only) {
        $abc .= ".abc";
    }   

    my %second = map {$_=>1} @files_abc; 
    my @same2 = grep { $second{$_} } @files_def; #@same and same2 are equal.
    my @def_only = grep { !$second{$_} } @files_def;
    foreach my $def (sort @def_only) {
        $def .= ".def";
    }

    my @combine_all = sort (@same, @abc_only, @def_only);
    print "\nCombine all:-\n @combine_all\n" ;
    print "\nList of files with same extension\n @same";  
    print "\nList of files with abc only\n @abc_only"; 
    print "\nList of files with def only\n @def_only"; 
    foreach my $item (sort @combine_all) {
        print FILE2 "$item\n" ;
    }
    close (FILE2) ;

你能帮我看一下吉斯错了吗?谢谢你。

5 个答案:

答案 0 :(得分:4)

总是添加

use strict;
use warnings;

到你的程序负责人。在您需要帮助之前,他们会发现最简单的错误。

  • 您应始终使用open FILE, "reflog" or die $!;
  • 检查文件是否已成功打开
  • 您使用的是不存在的变量$ine。你的意思是$line
  • 您在数组中读取的行包含尾随换行符。写chomp @lines;删除它们
  • 您的正则表达式错误,您需要||而不是&&。而是写if ($line =~ /\.(iif|isp)$/)

如果修复后仍有问题,请再次询问。

答案 1 :(得分:1)

除了已经指出的错误之外,您似乎从FUNC而不是FILE加载@lines。这也是一个错字吗?

另外,如果reflog真的包含一系列每行有一个文件名的行,为什么你会期望有条件的“if($ line =〜/ .abc /&amp;&amp; $ line =〜/ .def /)“评估为真?

如果您可以从您正在阅读的实际文件中发布示例,以及您正在调试的实际代码,那将非常有用。或至少编辑问题以解决已提到的错别字

答案 2 :(得分:0)

你不需要啜饮整个文件;你可以一次阅读一行。我认为此代码适用于reflog文件的扩展版本:

xx.pl

#!/usr/bin/env perl

use strict;
use warnings;

open my $file, '<', "reflog" or die "Failed to open file reflog for reading ($!)";
open my $func, '>', 'log'    or die "Failed to create file log for writing ($!)";

my ($oldline, $oldname, $oldextn) = ("", "", "");
while (my $newline = <$file>)
{
    chomp $newline;
    $newline =~ s/^\s*//;
    my ($newname, $newextn) = ($newline =~ m/(.*)([.][^.]*)$/);
    if ($oldname eq $newname)
    {
        # Found the same file - presumably $oldextn eq ".abc" and $newextn eq ".def"
        print $func "$newname\n";
        print "$newname\n";
        $oldline = "";
        $oldname = "";
        $oldextn = "";
    }
    else
    {
        print $func "$oldline\n" if ($oldline);
        print "$oldline\n" if ($oldline);
        $oldline = $newline;
        $oldname = $newname;
        $oldextn = $newextn;
    }
}
print $func "$oldline\n" if ($oldline);
print "$oldline\n" if ($oldline);

#unlink "reflog" ;
chmod 0644, "log";
close $func;
close $file;

由于代码实际上没有检查扩展名,因此省略$oldextn$newextn是可行的。另一方面,如果您非常担心需要处理前导空格的输入格式,您可能需要检查扩展名。

我很少发现像这样的处理脚本删除自己的输入很好,因此我已经将unlink "reflog";注释掉了;你的旅费可能会改变。我也经常只读取标准输入并写入标准输出;这将简化代码。此代码写入日志文件和标准输出;很明显,你可以省略任何输出流。我懒得编写一个函数来处理写作,所以print语句成对出现。

这是控制中断报告的变体。

引用日志

file1.abc
file1.def
file2.abc
file2.def
file3.abc
file3.def
file4.abc
file5.abc
file5.def
file6.def
file7.abc

输出

$ perl xx.pl
file1
file2
file3
file4.abc
file5
file6.def
file7.abc
$ cat log
file1
file2
file3
file4.abc
file5
file6.def
file7.abc
$ 

使用空行处理未分类的文件名

#!/usr/bin/env perl

use strict;
use warnings;

open my $file, '<', "reflog" or die "Failed to open file reflog for reading ($!)";
open my $func, '>', 'log'    or die "Failed to create file log for writing ($!)";

my @lines;

while (<$file>)
{
    chomp;
    next if m/^\s*$/;
    push @lines, $_;
}

@lines = sort @lines;

my ($oldline, $oldname, $oldextn) = ("", "", "");
foreach my $newline (@lines)
{
    chomp $newline;
    $newline =~ s/^\s*//;
    my ($newname, $newextn) = ($newline =~ m/(.*)([.][^.]*)$/);
    if ($oldname eq $newname)
    {
        # Found the same file - presumably $oldextn eq ".abc" and $newextn eq ".def"
        print $func "$newname\n";
        print "$newname\n";
        $oldline = "";
        $oldname = "";
        $oldextn = "";
    }
    else
    {
        print $func "$oldline\n" if ($oldline);
        print "$oldline\n" if ($oldline);
        $oldline = $newline;
        $oldname = $newname;
        $oldextn = $newextn;
    }
}
print $func "$oldline\n" if ($oldline);
print "$oldline\n" if ($oldline);

#unlink "reflog" ;
chmod 0644, "log";
close $func;
close $file;

这与我发布的原始代码非常相似。新线是这些:

my @lines;

while (<$file>)
{
    chomp;
    next if m/^\s*$/;
    push @lines, $_;
}

@lines = sort @lines;

my ($oldline, $oldname, $oldextn) = ("", "", "");    # Old
foreach my $newline (@lines)

这将读取'reflog'文件,跳过空白行,将其余部分保存在@lines数组中。当所有行都被读取时,它们被排序。然后,新代码不是从文件中读取循环,而是从排序的行数组中读取条目。其余的处理和以前一样。对于您描述的输入文件,输出为:

file1
file2
file3

Urgh:不需要chomp $newline;,尽管它不是有害的。过时的chopchomp的前身)会很危险。现代Perl得分为一。

答案 3 :(得分:0)

use strict;
use warnings;

my @files_abc;
my @files_def;
my $line;

open(FILE,'reflog') || die ("could not open reflog");

while ($line = <FILE>) {
    if($line=~ /(.*)\.abc/) {
        push(@files_abc,$1);
    }
    elsif($line=~ /(.*)\.def/) {
        push(@files_def,$1);
    }
}

close(FILE);

my %second = map {$_=>1} @files_def;
my @same = grep { $second{$_} } @files_abc;

print "\nList of files with same extension\n @same";


foreach my $abc (@files_abc) {
           $abc .= ".abc";
         }
foreach my $def (@files_def) {
           $def .= ".def";
         }

print "\nList of files with abc extension\n @files_abc";
print "\nList of files with def extension\n @files_def";

输出

List of files with same extension
file1 file2 file3 file5

List of files with abc extension
file1.abc file2.abc file3.abc file4.abc file5.abc file7.abc file10def.abc

List of files with def extension
file2.def file3.def file5.def file6.def file8abc.def file1.def file9abc.def

希望这会有所帮助......

答案 4 :(得分:-1)

open( FILE, "reflog" );
open( FUNC, '>log' );
my %seen;
while ( chomp( my $line = <FILE> ) ) {
    $line =~ s/^\s*//;
    if ( $ine =~ /(\.+)\.(abc|def)$/ ) {
        $seen{$1}++;
    }
}

foreach my $file ( keys %seen ) {
    if ( $seen{$file} > 1 ) {
        ## do whatever you want to
    }
}
unlink "reflog";
chmod( 0750, "log" );
close(FUNC);
close(FILE);