¿Cómo debería imprimir un carácter particular en el archivo después de leer el archivo?

StackOverflow https://stackoverflow.com/questions/969999

Pregunta

Estoy leyendo un archivo mediante script de perl. Este archivo consta de cadenas con diferentes personajes y se supone que debo identificar cadenas que contienen el carácter 'X'. Quiero saber cómo debo (1) imprimir esta cadena (que contenga 'X') y (2) escribir esta cadena a otro archivo (3) contar el número de 'X' personajes de todo el archivo . El siguiente script imprime todo el archivo de nuevo. ¿Alguna sugerencia?

#!/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;
¿Fue útil?

Solución

Dado que se trata de revisión de código, vamos a ir uno por uno:

#!/use/bin/perl

Esa línea es tinglado más probable es un error tipográfico. Probablemente debería ser

#!/usr/bin/perl

o lo vuelve which perl en su sistema.

use strict;
use warnings;

Buena.

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

No hay necesidad de paquete filehandles globales cuando se puede utilizar filehandles léxicos. La forma 3-argumento de open es preferible en estos días. Además, el mensaje de error debe indicar el fichero que no se podía abrir:

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

my @body = <FILE>;

Se le sorber el archivo en una matriz. Eso es completamente innecesario en este caso.

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

declarar e inicializar (si es necesario) las variables en el más pequeño alcance posible.

my $count;

El $string variable no se utiliza en ningún otro lugar en el código.

foreach $_(@body){

Esto es tonto. for utiliza $ _ Si no se especifica ninguna variable de bucle. Es más fácil mantener las cosas en su lugar si se especifica una variable de bucle léxico.

for my $line ( @body ) {

Sin embargo, no creo que usted debe sorber el archivo.

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

Esto da lugar a una persona compatible, si la línea contiene una X. Por lo tanto, es equivalente a /X/. Sin embargo, eso no le dirá la palabra que contenía la 'X'. Para eso, es necesario decidir qué es una palabra y hacer su juego en el nivel de palabra.

Con todo esto en mente, considere la siguiente secuencia de comandos. He hecho una suposición simplificada con respecto a lo que considero que es una palabra. Usted debe ser capaz de aprovechar este para satisfacer todos los requisitos:

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

ACTUALIZACIÓN: Si no se preocupan por encontrar las palabras dentro de cada línea que tienen uno o más caracteres X, el bucle while se simplificaría:

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

utilizando $ _. Eso, sin embargo, es probablemente ineficaz (teniendo en cuenta que estamos ahorrando cada personaje X emparejado). En este caso, tr funciona mejor:

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

Otros consejos

Está imprimiendo $_ en ambas ramas de su cláusula si. Deshacerse de la rama más.

Si se asume "cadena" en su pregunta es igual a "línea":

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;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top