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;
War es hilfreich?

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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top