Come devo stampare un particolare carattere nel file dopo aver letto il file?
-
13-09-2019 - |
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;
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;