我有一个打开.txt文件的脚本,创建一个数组,并做一些替换。然后我关闭并打开文件句柄,删除基于四列的重复行并保留最新的行。这一切都做我想要的。但是当我尝试在脚本中间没有打开和关闭的情况下运行它时,我得到一个空白文件。
#!/usr/bin/perl
use strict;
use warnings;
#use diagnostics;
my $file = "c:\\tmp.txt";
open( my $fh, "<", $file ) or die $!;
my $OUTNET = "c:\\NETtmp.txt";
open( OUTPUT, ">", "$OUTNET" ) or die $!;
my @array;
foreach (<$fh>) {
chomp;
if ($_ =~ m/^\s+\d/) {
$_ =~ s/^\s+//g;
$_ =~ s/\s+$//g;
$_ =~ s/\s+/,/g;
print " $_ \n";
printf OUTPUT "$_ \n";
}
}
close OUTPUT; # Do I need to save and then reopen the file here?
my $file2 = "c:\\NETtmp.txt";
my $OUTNET2 = "c:\\final.txt";
open my $in, '<', $file2 or die $!;
open my $out, '>', $OUTNET2 or die $!;
seek $in, 0, 0;
my %hash;
while (<$in>) {
my $key = join ',', ( split /,/ )[ 1, 2, 3, 4 ];
printf $out $_ unless $hash{$key}++;
}
close $out;
close $in;
答案 0 :(得分:2)
这段代码非常破碎,所以我会仔细研究并发表评论。
#!/usr/bin/perl
use strict;
use warnings;
#use diagnostics;
使用strict
和warnings
是一个好主意。
my $file = "c:\\tmp.txt";
open( my $fh, "+>", $file ) or die $!;
使用+
open
模式几乎总是错误的做法。如果更换内容是您想要的,那么写入新文件并将其复制到旧文件上要容易得多。
my $OUTtmp = "c:\\OUTtmp.txt";
open( OUTPUT, ">", "$OUTtmp" ) or die;
你永远不必引用这样的变量。我假设您正在尝试强制进行字符串化,但Perl会在需要时自动执行此操作。在这种情况下,"$OUTtmp"
与$OUTtmp
完全相同。
my @array;
请注意,@array
现在为空。
foreach (<$fh>) {
chomp;
if ( $_ =~ m/^\s+\d/ ) {
$_ =~ s/^\s+//g;
$_ =~ s/\s+$//g;
$_ =~ s/\s+/,/g;
# print " $_ \n";
# printf OUTPUT "$_ \n";
}
}
此循环只是遍历文件并更改行,但不会将它们存储在任何位置。所以任何改变都会丢失。
#close $fh;
#close OUTPUT;
seek $fh, 0, 0;
my %hash = @array;
请注意@array
为空,所以现在%hash
也是空的。
while (<$fh>) {
my $key = ( split /,/ )[ 1, 2, 3, 4 ];
这不太可能达到预期效果。您正在尝试将4个标量值分配给一个标量值,这种情况永远不会发生。标量上下文中的列表切片返回它将在列表上下文中返回的最后一个值。例如:
>perl -E"my $key = ( split /,/, 'a,b,c,d,e,f' )[ 1, 2, 3, 4 ]; say $key"
e
printf OUTPUT $_ unless $hash{$key}++;
}
我认为这是您尝试阅读文件并重复删除。这将仅重用原始文件而不进行更改,因为在前一个循环中执行的更改将丢失。
close $fh;
close OUTPUT;
程序结束时文件会自动关闭,因此您无需执行此操作。除非您正在处理光盘写入错误。
答案 1 :(得分:0)
文件模式&#34; +&gt;&#34;破坏文件。将文件模式更改为+&lt;看看是否有效:
open( my $fh, "+<", $file ) or die $!