Domanda

Sto leggendo un file utilizzando lo script Perl.Questo file è costituito da stringhe con caratteri diversi e dovrei identificare le stringhe contenenti il ​​carattere "X".Voglio sapere come dovrei (1) stampa questa stringa (contenente 'X') e anche (2) scrivi questa stringa in un altro file (3) conta il numero di caratteri "X" nell'intero file.Lo script seguente stampa nuovamente l'intero file.Eventuali suggerimenti?

#!/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;
È stato utile?

Soluzione

Poiché questa è la revisione del codice, procediamo uno per uno:

#!/use/bin/perl

Quella battuta è molto probabilmente un errore di battitura.Probabilmente dovrebbe esserlo

#!/usr/bin/perl

o qualunque cosa which perl ritorna sul tuo sistema.

use strict;
use warnings;

Bene.

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

Non sono necessari filehandle globali del pacchetto quando è possibile utilizzare filehandle lessicali.La forma a 3 argomenti di open è preferibile di questi tempi.Inoltre, il messaggio di errore dovrebbe indicare il file che non è stato possibile aprire:

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

my @body = <FILE>;

Stai assorbendo il file in un array.Ciò è del tutto inutile in questo caso.

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

Dichiara e inizializza (se necessario) qualsiasi variabile nell'ambito più piccolo possibile.

my $count;

La variabile $string non viene utilizzato in nessun'altra parte del codice.

foreach $_(@body){

Questo è sciocco. for utilizza $_ se non viene specificata alcuna variabile di ciclo.È più semplice mantenere le cose in chiaro se invece specifichi una variabile di ciclo lessicale.

for my $line ( @body ) {

Tuttavia, non penso che dovresti lerciare il file.

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

Ciò si traduce in una corrispondenza riuscita se la riga contiene una X.Quindi equivale a /X/.Tuttavia, ciò non ti dirà la parola che conteneva la "X".Per questo, devi decidere cos'è una parola ed effettuare la corrispondenza a livello di parola.

Tenendo presente tutto ciò, considera il seguente script.Ho fatto un presupposto semplificativo riguardo a ciò che considero una parola.Dovresti essere in grado di basarti su questo per soddisfare tutti i requisiti:

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

AGGIORNAMENTO: Se non ti interessa trovare le parole all'interno di ciascuna riga che contengono uno o più caratteri X, il ciclo while verrebbe semplificato:

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

utilizzando $_.Ciò, tuttavia, è probabilmente inefficiente (dato che stiamo salvando ogni carattere X corrispondente).In questo caso, tr funziona meglio:

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

Altri suggerimenti

Stai stampando $_ in entrambi i rami della clausola if.Sbarazzarsi del ramo else.

Supponendo che "stringa" nella tua domanda sia uguale a "linea":

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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top