2016-06-30 14 views
2

Mein Input File:Warum unterscheidet sich die Ausgabe bei Verwendung des folgenden Skripts?

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 $_; 
} 

Mein script1 Ausgang:

MVLSEGEWQLVLHVWAKVEADVAGHGQDILIRLFKSHPETLEKFDRFKHLKTEAEMKASEDLKKAGVTVLTALGAILKKKGHHEAELKPLAQSHATKHKIPIKYLEFISEAIIHVLHSRHPGNFGADAQGAMNKALELFRKDIAAKYKELGYQ 

Script2 Ausgabe:

103M:A|PDBID|CHAIN|SEQUENCE 
MVLSEGEWQLVLHVWAKVEADVAGHGQDILIRLFKSHPETLEKFDRFKHLKTEAEMKASEDLKKAGVTVLTALGAILKKKGHHEAELKPLAQSHATKHKIPIKYLEFISEAIIHVLHSRHPGNFGADAQGAMNKALELFRKDIAAKYKELGYQG 

Antwort

2

Das ist eigentlich eine interessante Frage, denn es gibt zwei verschiedene Perl-Konzepte im Spiel.

Die erste ist - <FH> bewirkt, dass eine Zeile aus der Datei gelesen wird.

Also, wenn Sie:

while (<FH>) { 

Was du bist eigentlich bekommen ist:

while (defined $_ = <FH>) { 

} 

Und eine Zeile aus dem Datei-Handle gelesen wird, setzen in $_ und es wird dann getestet wenn es "definiert" ist (zB war das Lesen in Ordnung) - und wenn nicht, verlässt es die Schleife.

Da im ersten Beispiel $_ nicht gedruckt wird, wird diese Zeile effektiv verworfen.

Aber die Sekunde denken im Spiel ist über Kontext.

<FH> funktioniert anders, wenn Sie tun:

my $line = <FH>; 

Und:

my @lines = <FH>; 

Im ersten Fall - eine einzige Zeile (bis zum nächsten $/ - standardmäßig \n) gelesen wird. Im letzteren Fall wird die gesamte Datei gelesen, eine "Zeile" pro Array-Element.

Nun ist dies wichtig, weil die while Schleife lesen - ist in einem skalaren Kontext (Zeile für Zeile). Aber der print <FH> ist ein Listenkontext - und bewirkt, dass die ganze Datei gelesen (und gedruckt) wird.

Also in Ihrem ersten Beispiel - Sie wiederholen die Schleife einmal. Die erste Zeile verwerfen und alles andere drucken.

Und in der zweiten Schleife - Iteration einmal pro Zeile und Drucken jeder Zeile.

Der Unterschied ist auf einer 2-zeilige Datei nicht offensichtlich, aber:

#!/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 

erhalten Sie folgende Ausgabe:

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

Aber Ihr zweites Beispiel zu nehmen:

#!/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 

Was gibt:

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 - es gibt keine chomp in den oben genannten, so $_ enthält Zeilenumbrüche.

Und während wir dabei sind - diese Form von open ist keine gute Praxis. Ich würde stattdessen vorschlagen:

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