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

#!/usr/bin/perl use warnings; use strict; # open your file using a filehandle called MYFILE open(MYFILE, "/root/prac/packages/test.txt"); my $data; while (<MYFILE>) { chomp; print <MYFILE>; #printing each line. Before e +nding the loop it prints entire file $data = join "", <MYFILE>; } print $data,"\n"; #prints entire file

My test.txt file contains

1st line 2nd line 3rd line 4th line End of file

Through these I expected the output is like it will print the entire file two times.But the o/p is

[root@ems packages]# perl variable_entire_file.pl 2nd line 3rd line 4th line Ending the file

Then I got doubt which line is printing either  print <MYFILE> or  print $data,"\n"; Afetr that i commented one by one. If i commented any one of two lines its giving the same output with the 1st line missing. Why its not printing two times. Why my 1st line missing

Replies are listed 'Best First'.
Re: Problem with reading the total file into variable
by Athanasius (Cardinal) on Aug 25, 2015 at 07:12 UTC

    Hello ravi45722,

    I see two problems. First, print takes a list as its argument; or, putting that round the other way, print imposes list context on its argument(s). So

    print <MYFILE>;

    reads in the whole of the rest of the file (after the first line, which was already read in via the <MYFILE> in the while condition) and prints that on the first iteration of the loop.

    Second, the line:

    $data = join "", <MYFILE>;

    does nothing, because the MYFILE filehandle is already pointing to the end of the file by the time it reaches this line. But if you were actually printing just the line already read in the while condition, the join would itself eat up the rest of the file, because it too imposes list context on its argument(s).

    I think you’re looking for something like this, which uses concatenation in place of join:

    use strict; use warnings; my $data; while (<DATA>) { print; $data .= $_; } print $data, "\n"; __DATA__ 1st line 2nd line 3rd line 4th line End of file

    Output:

    17:08 >perl 1355_SoPW.pl 1st line 2nd line 3rd line 4th line End of file 1st line 2nd line 3rd line 4th line End of file 17:08 >

    Note: I’ve taken out the call to chomp; why remove the newline if you want to put it back again when printing and concatenating?

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Problem with reading the total file into variable
by Corion (Patriarch) on Aug 25, 2015 at 07:01 UTC

    Your code is highly confused. There only is one instance of the MYFILE filehandle and the flow is as follows:

    1. while(<MYFILE>)... reads one line from the file into $_
    2. print <MYFILE> reads all remaining lines from MYFILE and prints them
    3. $data = join "", <MYFILE> assigns the empty string to $data because MYFILE is at the end of the file now.

    Maybe you can take a step back and explain why you are sprinkling various attempts to read from MYFILE over your code and what your real goal is?

      Thanks for reply. I want to do exactly what Athanasius did. From this I learn How  while<MYDATA> &  print <MYDATA> works.

Re: Problem with reading the total file into variable
by hippo (Archbishop) on Aug 25, 2015 at 08:23 UTC

    Others have pointed out some of the places where you have gone wrong in your original code. Here, I'd like to point out a recommended method from the FAQ.

    If, for some odd reason, you really want to see the whole file at once rather than processing line-by-line, you can slurp it in (as long as you can fit the whole thing in memory!):

    open my $in, '<', $file or die "Can't read old file: $! +" open my $out, '>', "$file.new" or die "Can't write new file: $ +!"; my $content = do { local $/; <$in> }; # slurp! # do your magic here print $out $content;

    There really is lots of good stuff in the FAQ and if you will be doing any work with files at all, then FAQ 5 (linked above) will serve you well. Good luck.

Re: Problem with reading the total file into variable
by 1nickt (Canon) on Aug 25, 2015 at 07:31 UTC

    Update: Hah! Brother Athanasius is nimbler of finger (not to mention grey matter) ...

    As Corion points out, <MYFILE> is a filehandle from which you read and process one line at a time; it doesn't represent a line itself. A corrected version of your code is below.

    [00:28][nick:~/monks]$ cat 1139778.txt foo bar baz qux
    #!/usr/bin/perl use strict; use warnings; # Don't hard-code filenames in logic code my $file = '1139778.txt'; # Use the three-argument form of open() ... open( my $MYFILE, '<', $file ) or die "Failed to open $file: $!\n"; # ... and always check for +success # Use parentheses to show we want the whole list of lines my $data = join '', (<$MYFILE>); print "Using \$data:\n$data\n\n"; # Go back to the beginning of the file seek $MYFILE, 0, 0; # No parentheses so we get one line at a time print "Using \$line:\n"; while ( my $line = <$MYFILE> ) { # chomp; # No need to chomp if you are printing the file out again print $line; } close $MYFILE or die "Failed to close $file: $!\n"; __END__
    Output:
    [00:29][nick:~/monks]$ perl 1139778.pl Using $data: foo bar baz qux Using $line: foo bar baz qux

    Hope this helps! Make sure you understand it all before you continue :-)

    The way forward always starts with a minimal test.
Re: Problem with reading the total file into variable
by james28909 (Deacon) on Aug 25, 2015 at 07:48 UTC

    Heres another way :)

    use strict; use warnings; #using three argument for open(); open ( my $output, '>', 'output' ) or die "cannot open file for writin +g -$!"; #read and print all on one line ;) print ( $output $_ ) while(<DATA>); __DATA__ 1st line 2nd line 3rd line 4th line End of file
Re: Problem with reading the total file into variable
by Anonymous Monk on Aug 25, 2015 at 07:56 UTC

      seems nobody proposed it so here is a way to do it

        seems nobody proposed it so here is a way to do it

        perlintro and Modern Perl both discuss this

        They also avoid a loop to slurp a file

Re: Problem with reading the total file into variable
by BillKSmith (Monsignor) on Aug 25, 2015 at 11:05 UTC
    Consider using a module.
    use strict; use warnings; use Slurp; my $data = slurp("/root/prac/packages/test.txt"); print $data;
    Bill
      :D A review of this module Slurp