I am trying to write a script which will count and erase empty lines from a file and save the changes in a new file:
if (@ARGV != 2) {
print "Usage: $0 infile outfile\n";
exit;
}
$infile = @ARGV[0];
$outfile = @ARGV[1];
open($old, "<$infile");
open($new, ">$outfile");
@mass = <$old>;
foreach $newc(@mass) {
$counter++;
if ($_ =~ /^$/) {
print "blank line found in $old at line number $counter\n";
print $new;
}
}
close($new);
close($old);
But it's not working. Where am I going wrong?
Here's another option:
use strict;
use warnings;
@ARGV == 2 or die "Usage: $0 infile outfile\n";
open my $fhIN, '<', $ARGV[0] or die $!;
open my $fhOUT, '>', $ARGV[1] or die $!;
while (<$fhIN>) {
if (/\S/) {
print $fhOUT $_;
}
else {
print "Blank at line $.\n";
}
}
As amon showed, you can iterate over your file's lines without first reading them into an array. This script also takes advantage of $.
, which contains the file's current line number. The regex /\S/
checks for any non-whitespace characters in the line, as this indicates a non-blank line. If /\S/
is true, it writes the line to outfile
, else it prints the blank-line notification.
The file handles are lexically scoped in the three-argument form of open
(the preferred method), so the files will automatically close
at the script's end.
You can even go a step further and take advantage of STDIN, STDOUT and STDERR for maximum flexibility and usefulness.
use strict;
use warnings;
while (<>) {
if (/\S/) {
print;
}
else {
print STDERRR "Blank at line $.\n";
}
}
Then just use
script.pl file.in >file.out
instead of
script.pl file.in file.out
but it also allows you to do stuff like
prog1 | script.pl | prog2