我有一个文件reflog
,内容如下。将有具有相同名称但不同扩展名的项目。我想检查每个项目(例如file1
,file2
和file3
),它需要存在于两个扩展中(.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) ;
你能帮我看一下吉斯错了吗?谢谢你。
答案 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
文件的扩展版本:
#!/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;
,尽管它不是有害的。过时的chop
(chomp
的前身)会很危险。现代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);