简体   繁体   中英

Perl's Chomp: Chomp is removing the whole word instead of the newline

I am facing issues with perl chomp function. I have a test.csv as below:

col1,col2
vm1,fd1
vm2,fd2
vm3,fd3
vm4,fd4

I want to print the 2nd field of this csv. This is my code:

#!/usr/bin/perl -w
use strict;

my $file = "test.csv";
open (my $FH, '<', $file);
my @array = (<$FH>);
close $FH;

foreach (@array)
{
    my @row = split (/,/,$_);
    my $var = chomp ($row[1]);     ###   <<< this is the problem
    print $var;
}

The output of aboe code is :

11111

I really don't know where the "1" is comming from. Actually, the last filed can be printed as below:

foreach (@array)
{
    my @row = split (/,/,$_);
    print $row[1];     ###  << Note that I am not printing "\n"
}  

the output is:

vm_cluster
fd1
fd2
fd3
fd4

Now, i am using these field values as an input to the DB and the DB INSERT statement is failing due this invisible newline. So I thought chomp would help me here. instead of chomping, it gives me "11111".

Could you help me understand what am i doing wrong here.

Thanks.

Adding more information after reading loldop's responce:

If I write as below, then it will not print anything (not even the "11111" output mentioned above)

foreach (@array)
{
    my @row = split (/,/,$_);
    chomp ($row[1]); 
    my $var = $row[1]; 
    print $var;
}

Meaning, chomp is removing the last string and the trailing new line.

The reason you see only a string of 1 s is that you are printing the value of $val which is the value returned from chomp . chomp doesn't return the trimmed string, it modifies its parameter in-place and returns the number of characters removed from the end. Since it always removes exactly one "\\n" character you get a 1 output for each element of the array.

You really should use warnings instead of the -w command-line option, and there is no reason here to read the entire file into an array. But well done on using a lexical filehandle with the three-parameter form of open .

Here is a quick refactoring of your program that will do what you want.

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

my $file = 'test.csv';
open my $FH, '<', $file or die qq(Unable to open "$file": $!);

while (<$FH>) {
    chomp;
    my @row = split /,/;
    print $row[1], "\n";
}

although, it is my fault at the beginning.
chomp function return 1 <- result of usage this function.
also, you can find this bad example below. but it will works, if you use numbers. sometimes i use this cheat (don't do that! it is my bad-hack code!)
map{/filter/ && $_;}@all_to_filter;
instead of this, use
grep{/filter/}@all_to_filter;

foreach (@array)
{
    my @row = split (/,/,$_);
    my $var = chomp ($row[1]) * $row[1];     ###   this is bad code!
    print $var;
}

foreach (@array)
{
    my @row = split (/,/,$_);
    chomp ($row[1]);
    my $var = $row[1];  
    print $var;
}

If you simply want to get rid of new lines you can use a regex:

my $var = $row[1];
$var=~s/\n//g;

So, I was quite frustrated with this easy looking task bugging me for the whole day long. I really appreciate everyone who responded.

Finaly I ended up using Text::CSV perl module and then calling each of the CSV field as array reference. There was no need left to run the chomp after using Text::CSV.

Here is the code:

#!/usr/bin/perl 
use warnings;
use strict;
use Text::CSV;


 my $csv = Text::CSV->new ( { binary => 1 } )  # should set binary attribute.
                  or die "Cannot use CSV: ".Text::CSV->error_diag ();


open my $fh, "<:encoding(utf8)", "vm.csv" or die "vm.csv: $!";

<$fh>;  ## this is to remove the column headers.

while ( my $row = $csv->getline ($fh) )
{
    print $row->[1];
}

and here is hte output:

fd1fd2fd3fd4 

Later i was pulled these individual values and inserted into the DB.

Thanks everyone.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM