sago
sago

Reputation: 787

Why output differs while using following script?

My Input File:

103M:A|PDBID|CHAIN|SEQUENCE
MVLSEGEWQLVLHVWAKVEADVAGHGQDILIRLFKSHPETLEKFDRFKHLKTEAEMKASEDLKKAGVTVLTALGAILKKKGHHEAELKPLAQSHATKHKIPIKYLEFISEAIIHVLHSRHPGNFGADAQGAMNKALELFRKDIAAKYKELGYQG

Script1:

open(FH,"103m.txt")||die "error";
while(<FH>)
{
    print <FH>;
}

script2:

open(FH,"103m.txt")||die "error";
while(<FH>)
{
    print $_;
}

My script1 output:

MVLSEGEWQLVLHVWAKVEADVAGHGQDILIRLFKSHPETLEKFDRFKHLKTEAEMKASEDLKKAGVTVLTALGAILKKKGHHEAELKPLAQSHATKHKIPIKYLEFISEAIIHVLHSRHPGNFGADAQGAMNKALELFRKDIAAKYKELGYQ

Script2 output:

103M:A|PDBID|CHAIN|SEQUENCE
MVLSEGEWQLVLHVWAKVEADVAGHGQDILIRLFKSHPETLEKFDRFKHLKTEAEMKASEDLKKAGVTVLTALGAILKKKGHHEAELKPLAQSHATKHKIPIKYLEFISEAIIHVLHSRHPGNFGADAQGAMNKALELFRKDIAAKYKELGYQG

Upvotes: 2

Views: 49

Answers (1)

Sobrique
Sobrique

Reputation: 53478

This is actually an interesting question, because there's two different perl concepts in play.

The first is - <FH> causes a line to be read from the file.

So if you:

while ( <FH> ) {

What you're actually getting is:

while ( defined $_ = <FH> ) { 

}

And a line is being read from the file handle, put in $_ and then it's tested if it's 'defined' (e.g. the read was ok) - and if it wasn't, it exits the loop.

Because in the first example - you don't print $_ - that line is effectively discarded.

But the second think in play is about context.

<FH> works differently if you do:

my $line = <FH>;

And:

my @lines = <FH>; 

In the former case - a single line is read (up to the next $/ - by default \n). In the latter, the whole file will be read, one "line" per array element.

Now, this is important because the while loop read - is in a scalar context (one line at a time). But the print <FH> is a list context - and will cause the whole file to be read (and printed).

So in your first example - you're iterating the loop once. Discarding the first line, and printing everything else.

And in the second loop - you're iterating once per line, and printing each line.

The difference isn't obvious on a 2 line file, but:

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

my $count; 

while ( <DATA> ) {
   print "Loop count ", ++$count,"\n";
   print '$_ is "', $_,"\"\n";
   print "Printing <DATA>\n";
   print <DATA>;
}

__DATA__
line 1 
line 2
line 3
line 4
line 5

This will output:

Loop count 1
$_ is "line 1 
"
Printing <DATA>
line 2
line 3
line 4
line 5

But to take your second example:

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

my $count; 

while ( <DATA> ) {
   print "Loop count ", ++$count,"\n";
   print '$_ is "', $_,"\"\n";
   print 'printing $_',"\n";
   print $_;
}

__DATA__
line 1 
line 2
line 3
line 4
line 5

Which gives:

Loop count 1
$_ is "line 1 
"
printing $_
line 1 
Loop count 2
$_ is "line 2
"
printing $_
line 2
Loop count 3
$_ is "line 3
"
printing $_
line 3
Loop count 4
$_ is "line 4
"
printing $_
line 4
Loop count 5
$_ is "line 5"
printing $_
line 5

NB - there's no chomp in the above, so $_ includes newlines.

And whilst we're at it - that form of open isn't good practice. I would suggest instead:

open ( my $input, '<', "103m.txt" ) or die $!; 

Upvotes: 2

Related Questions