Вам не нужно хлебать весь файл;Вы можете читать по одной строке за раз.Я думаю, что этот код работает с этой расширенной версией вашего 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
идут парами.
Это вариант отчетов об отключении управления.
reflog
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
Ург: chomp $newline;
не требуется, хотя в противном случае он не является вредным.Старомодный chop
(предшественник chomp
) был бы опасен.Оценка один для современного Perl.