Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Newline's creep in, while using Tie::File

by always_coys (Novice)
on Nov 16, 2020 at 20:30 UTC ( [id://11123712]=perlquestion: print w/replies, xml ) Need Help??

always_coys has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,

This is the first time I am asking a question! I am trying to read a block of data (by matching a string) from one file and paste it in another file, at a specific line number. I have used the Tie::File option for the second file. My data in the first file (input file), is as follows:

NODE 32 0.00000 0.00000 -1.90000 NODE 33 0.00000 0.00000 -5.50000 NODE 34 0.00000 0.00000 -9.00000 NODE 35 0.00000 0.00000 -15.00000 NODE 36 0.00000 0.00000 -18.90000 NODE 37 0.00000 0.00000 -22.40000 NODE 38 0.00000 0.00000 -25.90000 NODE 39 0.00000 0.00000 -29.00000 NODE 40 0.00000 0.00000 -32.50000 NODE 41 0.00000 0.00000 -33.90000 NODE 42 0.00000 0.00000 -62.90000 BEAM 26 27 26 1 14 1 BEAM 27 28 27 1 13 1 BEAM 28 29 28 1 12 1 BEAM 29 30 29 1 11 1 BEAM 30 31 30 1 10 1 BEAM 31 32 31 1 9 1 BEAM 32 33 32 1 8 1 BEAM 33 34 33 1 7 1 BEAM 34 35 34 1 6 1 BEAM 35 36 35 1 5 1 BEAM 36 37 36 1 4 1

And the code I have written, is this:

use Tie::File; my @records; tie @records, 'Tie::File', "pile_out.txt"; # file containing data $in_file = "fake_vals.fem"; # specific line number in the output file. The data from the input # file should be written at this line. $seed_line = 10; open(IN,"$in_file") or die("cannot open the log file for reading\n"); # NODE is the string to be matched with, in the data from the # input file while(<IN>){######to read the input file $records[$seed_line] = "$_" if($_=~/\bNODE\b/i); $seed_line++; } close(IN);

The result I need is the following to be printed in the output file, starting at line no. 11 in the output file. All lines in the input file, starting with the string NODE should be printed in the output file, without any empty line in between.

NODE 32 0.00000 0.00000 -1.90000 NODE 33 0.00000 0.00000 -5.50000 NODE 34 0.00000 0.00000 -9.00000 NODE 35 0.00000 0.00000 -15.00000 NODE 36 0.00000 0.00000 -18.90000 NODE 37 0.00000 0.00000 -22.40000 NODE 38 0.00000 0.00000 -25.90000 NODE 39 0.00000 0.00000 -29.00000 NODE 40 0.00000 0.00000 -32.50000 NODE 41 0.00000 0.00000 -33.90000 NODE 42 0.00000 0.00000 -62.90000

However, my code is printing newlines after very single line of data, in the output file, as shown below.

NODE 32 0.00000 0.00000 -1.90000 NODE 33 0.00000 0.00000 -5.50000 NODE 34 0.00000 0.00000 -9.00000 NODE 35 0.00000 0.00000 -15.00000 NODE 36 0.00000 0.00000 -18.90000 NODE 37 0.00000 0.00000 -22.40000 NODE 38 0.00000 0.00000 -25.90000 NODE 39 0.00000 0.00000 -29.00000 NODE 40 0.00000 0.00000 -32.50000 NODE 41 0.00000 0.00000 -33.90000 NODE 42 0.00000 0.00000 -62.90000

Could you please tell me where I went wrong. This is the first time I have tried using Tie::File.

Replies are listed 'Best First'.
Re: Newline's creep in, while using Tie::File
by choroba (Cardinal) on Nov 16, 2020 at 20:34 UTC
    It seems Tie::File stores the lines without final newlines. Run chomp at the top of the while loop to remove newlines from the lines you want to store.

    Update: After reading the documentation, I can confirm the behaviour. You can use the autochomp option to turn this behaviour off.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
      Thanks a lot! It has worked.
Re: Newline's creep in, while using Tie::File
by GrandFather (Saint) on Nov 16, 2020 at 20:52 UTC

    Your immediate problem is that you read lines from a file with <IN> into the default variable and "write" them immediately into the tied object. However the tied object is essentially an array of lines. Because you haven't stripped the line end character from the input line you end up with two line ends on output.

    However, there is a pile of other stuff that needs attention in your sample code. Consider this reworked version:

    use strict; use warnings; use Tie::File; my @records; tie @records, 'Tie::File', "pile_out.txt"; my $in_file = "fake_vals.fem"; my $outIndex = 10; open my $in, '<', "$in_file" or die "cannot open '$in_file' for readin +g: $!\n"; while (my $line = <$in>) { next if $line !~ /\bNODE\b/i; chomp $line; $records[$outIndex] = $line; ++$outIndex; }

    First off, always use strictures (use strict; use warnings; - see The strictures, according to Seuss).

    Always use lexical file handles. In combination with strictures that will save some very embarrassing file messes.

    Always use three parameter open. Usually at this point we suggest or die, but you are doing that already - great! However show the actual file path you were trying to open and the failure message. That will save a couple of iterations of debugging.

    Avoid using the default variable. Using a manifest named variable helps with code readability and helps maintenance. It also avoids subtle problems with the default variable changing content when you don't expect it to.

    A more contentions, but only marginally important suggestion is to use the pre increment operator unless logic demands the post increment operator. As a general rule stuff toward the end of a line gets lost and increment is important so do it up front.

    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond

      First off, always use strictures

      If they should always be used...why are they not on by default?

        If they should always be used...why are they not on by default?

        For backwards compatibility. Making strictures on by default for newer versions of Perl would break most old or poorly written Perl code. If you use 5.012; strictures are on by default.

        Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
        Perl 7 (not sure of the equivalent 5.x version but I think it is 5.32.0) is starting off with strict and warnings 'on' by default. They are not on by default in 5.x because it would break a lot of existing code.
Re: Newline's creep in, while using Tie::File (use strict and warnings References)
by eyepopslikeamosquito (Archbishop) on Nov 18, 2020 at 01:09 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11123712]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (4)
As of 2024-04-23 23:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found