开发者

removing a matched line using csv module in perl

So far, I figured out how to match a line from a csv file using this perl module, Text::CSV_XS. What I need help is removing that line in the file. Is there an easy way to do this? Is there a way to do this in this module?

use strict;
use war开发者_如何学Cnings;
use Text::CSV_XS;

my @rows;
my $csv = Text::CSV_XS->new ({ binary => 1 }) or
     die "Cannot use CSV: ".Text::CSV_XS->error_diag ();
open my $fh, "<:encoding(UTF-16LE)", "Test.txt" or die "cannot open file: $!";
while (my $row = $csv->getline ($fh)) {

    if ($row->[0] =~ m/ABCDE/)
    {
      print "We have a match, remove the line \n";
    }
    else
    {
        print "No match found\n";
    }
}
$csv->eof or $csv->error_diag ();
close $fh;


It doesn't look like that module can do that, but there are a number of other Perl modules that can:

  • Tie::Handle::CSV
  • Tie::CSV_File

See the links for documentation and examples.


The only way to remove content from a file is to read the file and write out the new contents. A common way to do this is to open another file for writing, read records from the input file and write only those records you wish to keep to the output file. Then close both, unlink or rename the original (depending on whether you want to keep a backup), and then rename the output file to the original input file name.


I am not sure if Text::CSV_XS allows you to remove lines. I do not think it does.
One way to remove a line is when you read lines in your while loops, just store the lines you need.
After you close the file, just overwrite it with all the lines that you want to keep in the file.
So in your case anything that did not match ABCDE should be saved and later on written back into same file.
So you will endup with reading 10 lines and writing back 9 (assuming one line had ABCDE).


First, i would just parse the CSV file.

use Text::CSV_XS qw( csv );
$parsed_file_array_of_hashesv = csv(
    in      => "$input_csv_filename",
    sep     => ';',
    headers => "auto"
);    # as array of hash

Second, once you have the $parsed_file_array_of_hashesv, now you can loop that array in perl and detect the line you want to remove from the array. and then remove it using

splice ARRAY, OFFSET, LENGTH

removes anything from the OFFSET index through the index OFFSET+LENGT

lets assume index 0

my @extracted_array = @$parsed_file_array_of_hashesv;    #dereference hashes reference
splice @extracted_array, 0, 1;#remove entry 0
$ref_removed_line_parsed = \@extracted_array;            #referece to array

Third, write back the array to the CSV file

$current_metric_file    = csv(
    in      => $ref_removed_line_parsed,                 #only accepts referece
    out     => "$output_csv_filename",
    sep     => ';',
    eol     => "\n",                                   # \r, \n, or \r\n or undef
    #headers => \@sorted_column_names,              #only accepts referece
    headers => "auto"
); 

Notice, that if you use the \@sorted_column_names you will be able to control the order of the columns

my @sorted_column_names;
foreach my $name (sort {lc $a cmp lc $b} keys %{ $parsed_file_array_of_hashesv->[0] }) { #all hashes have the same column names so we choose the first one
    push(@sorted_column_names,$name);
}

That should write the CSV file without your line.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜