开发者

Perl problems printing output to a new file

I wa开发者_运维技巧nt to remove all lines in a text file that start with HPL_ I have acheived this and can print to screen, but when I try to write to a file, I just get the last line of the amended text printed in the new file. Any help please!

open(FILE,"<myfile.txt"); 
@LINES = <FILE>; 
close(FILE); 
open(FILE,">myfile.txt"); 
foreach $LINE (@LINES) { 
@array = split(/\:/,$LINE); 


my $file = "changed";

open OUTFILE, ">$file" or die "unable to open $file $!";

print OUTFILE $LINE unless ($array[0] eq "HPL_");

} 
close(FILE); 
close (OUTFILE);




exit;


You just want to remove all lines that start with HPL_? That's easy!

perl -pi -e 's/^HPL_.*//s' myfile.txt

Yes, it really is just a one-liner. :-)


If you don't want to use the one-liner, re-write the "write to file" portion as follows:

my $file = "changed";
open( my $outfh, '>', $file ) or die "Could not open file $file: $!\n";
foreach my $LINE (@LINES) { 
  my @array = split(/:/,$LINE);
  next if $array[0] eq 'HPL_';
  print $outfh $LINE;
}
close( $outfh );

Note how you are open()ing the file each time through the loop. This is causing the file to only contain the last line, as using open() with > means "overwrite what's in the file". That's the major problem with your code as it stands.

Edit: As an aside, you want to clean up your code. Use lexical filehandles as I've shown. Always add the three lines that tchrist posted at the top of every one of your Perl programs. Use the three-operator version of open(). Don't slurp the entire file into an array, as if you try to read a huge file it could cause your computer to run out of memory. Your program could be re-written as:

#!perl

use strict;
use autodie; 
use warnings FATAL => "all";

my $infile = "myfile.txt";
my $outfile = "changed.txt";

open( my $infh, '<', $infile );
open( my $outfh, '>', $outfile );
while( my $line = <$infh> ) {
    next if $line =~ /^HPL_/;
    print $outfh $line;
}
close( $outfh );
close( $infh );

Note how with use autodie you don't need to add or die ... to the open() function, as the autodie pragma handles that for you.


The issue with your code is that you open the file for output within your line-processing loop which, due to your use of the '>' form of open, opens the file each time for write, obliterating any previous content.

Move the invocation of open() to the top of your file, above the loop, and it should work.

Also, I'm not sure of your intent but at line 4 of your example, you reopen your input file for write (using '>'), which also clobbers anything it contains.

As a side note, you might try reading up on Perl's grep() command which is designed to do exactly what you need, as in:

#!/usr/bin/perl
use strict;
use warnings;

open(my $in, '<', 'myfile.txt') or die "failed to open input for read: $!";
my @lines = <$in> or die 'no lines to read from input';
close($in);

# collect all lines that do not begin with HPL_ into @result
my @result = grep ! /^HPL_/, @lines; 

open(my $out, '>', 'changed.txt') or die "failed to open output for write: $!";
print { $out } @result;
close($out);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜