Wie soll ich nach dem Lesen der Datei ein bestimmtes Zeichen in der Datei ausdrucken?
-
13-09-2019 - |
Frage
Ich lese eine Datei mit Perl-Skript. Diese Datei besteht aus Strings mit verschiedenen Charakteren und ich sollte Strings identifizieren, das Zeichen ‚X‘ enthält. Ich möchte wissen, wie soll ich das (1) diese Zeichenfolge drucken (mit ‚X‘) und auch (2) schreiben diese Zeichenfolge in eine andere Datei (3) zählen die Anzahl der ‚X‘ Zeichen in der gesamten Datei . Das Skript unten druckt die gesamte Datei erneut. Irgendwelche Vorschläge?
#!/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;
Lösung
Da dieser Code-Review ist, gehen wir eins nach dem anderen:
#!/use/bin/perl
Die Shebang-Zeile ist höchstwahrscheinlich ein Tippfehler. Es sollte wohl sein
#!/usr/bin/perl
oder was auch immer which perl
kehrt auf Ihrem System.
use strict;
use warnings;
Gut.
open (FILE, "/home/user/Desktop/infile.phy") || die "cant open file\n";
Keine Notwendigkeit für Paket global Dateihandies wenn Sie lexikalische Dateihandies verwenden können. Die 3-Argument Form von open
ist in diesen Tagen bevorzugt. Auch sollte die Fehlermeldung, die Datei anzuzeigen, die Sie konnte nicht geöffnet werden:
my $filename = '/home/user/Desktop/infile.phy';
open my $input, '<', $filename
or die "Cannot open '$filename' for reading: $!";
my @body = <FILE>;
Sie schlürfen die Datei in ein Array. Das ist völlig unnötig in diesem Fall.
my $count = 0;
my $string = '';
Deklarieren und (falls erforderlich) alle Variablen im kleinstmöglichen Rahmen initialisieren.
my $count;
Die Variable $string
ist nirgendwo sonst in Ihrem Code verwendet wird.
foreach $_(@body){
Das ist albern. for
verwendet $ _, wenn keine Schleifenvariable angegeben wird. Es ist einfacher, die Dinge gerade zu halten, wenn Sie stattdessen eine lexikalische Schleifenvariable angeben.
for my $line ( @body ) {
Aber ich glaube nicht, sollten Sie die Datei schlürfen.
if ($_ =~ m/[X]/){
Das führt zu einem erfolgreichen Spiel, wenn die Linie auf eine X. enthält Also, es zu /X/
entspricht. Aber das wird Sie das Wort nicht sagen, dass das ‚X‘ enthalten ist. Dafür müssen Sie entscheiden, was ein Wort ist und tun Sie Ihren Matching auf Wortebene.
Mit allem daran, betrachten Sie das folgende Skript. Ich habe eine vereinfachende Annahme gemacht in Bezug auf was ich als ein Wort sein. Sie sollten alle Anforderungen gerecht zu werden, darauf aufzubauen fähig sein:
#!/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: Wenn Sie nicht die Worte, egal in jeder Zeile zu finden, die ein oder mehr X-Zeichen haben, würde die while-Schleife vereinfacht:
while ( <$input> ) {
$count += (my @matches = /(X)/g );
print if @matches;
}
von _ $ verwenden. Das aber ist wahrscheinlich ineffizient (vorausgesetzt, dass wir uns abgestimmt X-Zeichen speichern). In diesem Fall tr
am besten funktioniert:
my ($count, $n);
$n = tr/X// and $count += $n and print while <$input>;
Andere Tipps
Sie drucken $_
in beiden Zweigen des if-Klausel. Lassen Sie sich von dem anderen Zweig los zu werden.
"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;