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.
精彩评论