Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I write only certain lines of a file in Perl?

Tags:

regex

grep

csv

perl

I am looking for a way to read an input file and print only select lines to an output file in Perl. The lines I want to print to the output file all begin with xxxx.xxxx.xxxx, where x is an alphanumeric character (the periods are periods, not wildcards). The lines do not all have the same ending, if that makes a difference. I'm thinking something like the following (the condition of the if statement is all that is really missing as far as I can tell).

open(IN, "<$csvfile");
my @LINES = <IN>;
close(IN);
open(OUT, ">$csvnewfile");
print OUT @LINES if ([line starts with xxxx.xxxx.xxxx]);
close(OUT);

Thanks in advance!

like image 489
ryantmer Avatar asked Feb 22 '10 22:02

ryantmer


2 Answers

Here is a better way to loop through your lines. It avoids loading your whole input file into memory at once:

use strict;
use warnings;

open my $fhi, '<', $csvfile    or die "Can not open file $csvfile: $!";
open my $fho, '>', $csvnewfile or die "Can not open file $csvnewfile: $!";
while (<$fhi>) {
    print $fho $_ if m/^ \w{4} \. \w{4} \. \w{4} /x;
}
close $fho;
close $fhi;

Keep in mind that the \w character class also includes underscores. To avoid underscores:

print $fho $_ if m/^ [a-z\d]{4} \. [a-z\d]{4} \. [a-z\d]{4} /xi;
like image 54
toolic Avatar answered Sep 27 '22 15:09

toolic


Style tips:

  • use lexical filehandles
  • check the result of open
  • also a good idea to check the result of close on a handle opened for writing

See below:

#! /usr/bin/perl

use warnings;
use strict;

die "Usage: $0 old new\n" unless @ARGV == 2;

my($csvfile,$csvnewfile) = @ARGV;

open my $in,  "<", $csvfile    or die "$0: open $csvfile: $!";
open my $out, ">", $csvnewfile or die "$0: open $csvnewfile: $!";

while (<$in>) {
  print $out $_ if /^\w{4}\.\w{4}\.\w{4}/;
}

close $out or warn "$0: close $csvnewfile: $!";
like image 28
Greg Bacon Avatar answered Sep 27 '22 15:09

Greg Bacon