Unexpected string concatenation result

I wrote the following code to read from a list of file names of files on each line and add some data to it.

open my $info,'<',"abc.txt"; while(<$info>){ chomp $_; my $filename = "temp/".$_.".xml"; print"\n"; print $filename; print "\n"; } close $info; 

Contents abc.txt

 file1 file2 file3 

Now I was expecting my code to give me the following output

 temp/file1.xml temp/file2.xml temp/file3.xml 

but instead I get the output

 .xml/file1 .xml/file2 .xml/file3 
+6
source share
2 answers

Your file has line endings \r\n . chomp removes \n ( Newline ), but leaves \r ( Carriage Return ). Using Data::Dumper with Useqq , you can check the variable:

 use Data::Dumper; $Data::Dumper::Useqq = 1; print Dumper($filename); 

This should output something like:

 $VAR1 = "temp/file1\r.xml"; 

In normal printing, it will display temp/file , move the cursor to the beginning of the line, and overwrite temp with .xml .

To remove line endings, replace chomp with:

 s/\r\n$//; 

or as @Borodin pointed out :

 s/\s+\z//; 

which "has the advantage of working for any line terminator, as well as removing the trailing space, which is usually undesirable"

+7
source

As already mentioned, your file has Windows line endings.

The following stand-alone example demonstrates what you are working with:

 use strict; use warnings; open my $info, '<', \ "file1\r\nfile2\r\nfile3\r\n"; while(<$info>){ chomp; my $filename = "temp/".$_.".xml"; use Data::Dump; dd $filename; print $filename, "\n"; } 

Outputs:

 "temp/file1\r.xml" .xml/file1 "temp/file2\r.xml" .xml/file2 "temp/file3\r.xml" .xml/file3 

Now there are two ways to fix this.

  • Adjust $INPUT_RECORD_SEPARATOR to your file.

     local $/ = "\r\n"; while(<$info>){ chomp; 

    chomp automatically works with the value of $/ .

  • Use regex instead of chomp to break line endings

    Since perl 5.10 there is an \R escape code that denotes a common newline.

     while(<$info>){ s/\R//; 

    Alternatively, you can simply remove all the intervals between steps to be more confident in covering your bases:

     while(<$info>){ s/\s+\z//; 
0
source

Source: https://habr.com/ru/post/974028/


All Articles