2009-06-09 3 views
0

Ich lese eine Datei mit Perl-Skript. Diese Datei besteht aus Zeichenfolgen mit unterschiedlichen Zeichen und ich soll Zeichenfolgen mit dem Zeichen 'X' identifizieren. Ich möchte wissen, wie sollte ich (1) diese Zeichenfolge drucken (mit 'X') und auch (2) schreibe diese Zeichenfolge in eine andere Datei (3) zählen Sie die Anzahl der 'X' Zeichen in der gesamten Datei. Das folgende Skript druckt die gesamte Datei erneut. Irgendwelche Vorschläge?Wie soll ich nach dem Lesen der Datei ein bestimmtes Zeichen in der Datei ausdrucken?

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

open (FILE, "/home/user/Desktop/infile.phy") || die "cant open file\n"; 
my @body = <FILE>; 
close (FILE); 
my $count= 0; 
my $string = ''; 
foreach $_(@body){ 
    if ($_ =~ m/[X]/){ 
     print "$_"; 
     $count++; 
     print $count; 
    } 
    else { 
     print ; 
    } 
} 
exit; 
+1

Ist das Hausaufgaben? –

+1

Ich dachte das gleiche, aber es könnte genauso gut ein Beispielproblem aus einem einleitenden Text sein. – inkedmn

+1

Irgendwann müssen Sie Ihre 'andere Datei' öffnen und sicherstellen, dass Sie darauf schreiben. Versuchen Sie auch, diese Form von "offen" zu vermeiden; Verwenden Sie ein Formular, das den Dateizugriffspunkt für die Verwendung mit einer regulären $ -Variablen zurückgibt: open ($ fh, "filename"); oder eine der Varianten. –

Antwort

4

Da dieser Code-Review ist, die einer nach dem anderen gehen lassen:

#!/use/bin/perl 

dieser Linie sheBANG ist höchstwahrscheinlich ein Tippfehler . Es sollte wahrscheinlich

#!/usr/bin/perl 

oder was auch immer which perl auf Ihrem System zurückgibt.

use strict; 
use warnings; 

Gut.

open (FILE, "/home/user/Desktop/infile.phy") || die "cant open file\n"; 

Keine Notwendigkeit für globale Dateihandles des Pakets, wenn Sie lexikalische Dateihandles verwenden können. Die 3-Argumente-Form von open ist heutzutage vorzuziehen. Auch sollte die Fehlermeldung, die Datei anzuzeigen, die Sie nicht öffnen können:

my $filename = '/home/user/Desktop/infile.phy'; 
open my $input, '<', $filename 
    or die "Cannot open '$filename' for reading: $!"; 

my @body = <FILE>; 

Sie die Datei in ein Array schlürfen. Das ist in diesem Fall völlig unnötig.

my $count = 0; 
my $string = ''; 

Deklarieren und initialisieren (falls erforderlich) alle Variablen im kleinstmöglichen Bereich.

my $count; 

Die Variable $string ist nirgendwo sonst in Ihrem Code verwendet.

foreach $_(@body){ 

Das ist albern. for verwendet $ _, wenn keine Schleifenvariable angegeben ist. Es ist einfacher, die Dinge beizubehalten, wenn Sie stattdessen eine lexikalische Schleifenvariable angeben.

for my $line (@body) { 

Aber ich glaube nicht, dass Sie die Datei schlürfen sollte.

 if ($_ =~ m/[X]/){ 

, die in einem erfolgreichen Spiel ergibt, wenn die Leitung also ein X enthält, ist es zu /X/ gleichwertig. Das wird Ihnen jedoch das Wort, das das 'X' enthielt, nicht sagen. Dafür müssen Sie entscheiden, was ein Wort ist und Ihren Abgleich auf Wort-Ebene vornehmen.

Mit diesem Gedanken betrachte das folgende Skript. Ich habe eine vereinfachende Annahme in Bezug darauf gemacht, was ich als ein Wort betrachte.

#!/usr/bin/perl 

use strict; 
use warnings; 

my $filename = "$ENV{TEMP}/test.txt"; 
open my $input, '<', $filename 
    or die "Cannot open '$filename' for reading: $!"; 

my $count; 

while (my $line = <$input>) { 
    my @words = grep { /X/ } split /\b/, $line; 
    $count += @words; 
    print join(', ', @words), "\n"; 
} 

print "$count\n"; 

__END__ 

UPDATE: Sie sollten alle Anforderungen gerecht zu werden, darauf aufzubauen in der Lage Wenn Sie nicht die Worte, egal in jeder Zeile zu finden, die ein oder mehr X-Zeichen haben, würde die while-Schleife sein vereinfacht:

while (<$input>) { 
    $count += (my @matches = /(X)/g); 
    print if @matches; 
} 

mit $ _. Dies ist jedoch wahrscheinlich ineffizient (da wir jedes übereinstimmende X-Zeichen speichern). In diesem Fall arbeitet tr am besten:

my ($count, $n); 
$n = tr/X// and $count += $n and print while <$input>; 
+0

Ich stimme all Ihren Anmerkungen zu. Punkt 3 in der Frage fragt jedoch "Zählen Sie die Anzahl von 'X' Zeichen in der ganzen Datei". Ihre Lösung zählt stattdessen die Anzahl der Wörter (Zeichenfolgen, die von der Definition von "Zeichenfolgen" abhängen), die ein "X" -Zeichen enthalten. – user55400

+0

@blixtor: Danke, dass du das eingefangen hast. Natürlich könnte jedes Wort mehrere X-Zeichen enthalten. Tatsächlich ist mir jetzt klar, dass das OP sich nicht darum kümmerte, die Zeilen in Wörter usw. aufzuteilen. –

+0

Die 3-Arg-Form von open ist manchmal nützlich und manchmal nicht. Es ist einfach, 2-arg immer sicher zu verwenden, und manchmal möchten Sie, dass Sie Standard-IO-Layer aus dem offenen Pragma oder -C-Switch übernehmen können. Wenn Sie 2-Arg-Opens kritisieren, sagen Sie zumindest, "weil Sie vielleicht irgendwann einmal einen variablen Dateinamen verwenden", nicht nur "es ist der neue Weg, es zu tun". – ysth

1

Sie drucken $_ in beiden Zweigen des if-Klausel. Befreie den else-Zweig.

+0

Es ist vielleicht für einen Neuling nicht offensichtlich, dass "drucken"; druckt $ _, aber genau das passiert. –

+0

genau. Ich hätte etwas ausführlicher sein können. Es tut uns leid. – innaM

0

"string" in Ihrer Frage Unter der Annahme gleich "Linie":

use strict; 
use warnings; 

@ARGV=qw(/home/user/Desktop/infile.phy); 

my $count = 0; 
open my $outfile, '>', 'outfile' or die $!; 
while (<>) { 
    my $cnt = tr/X/X/; 
    if ($cnt) { 
    print; 
    print $outfile $_; 
    } 
    $count += $cnt; 
} 

close $outfile or die $!; 

print $count; 
Verwandte Themen