Pergunta

Estou lendo um arquivo usando o script perl. Este arquivo consiste de cordas com personagens diferentes e eu deveria identificar seqüências contendo o caractere 'X'. Eu quero saber como devo (1) imprimir essa string (contendo 'X') e também (2) escrever esta string para um outro arquivo (3) contar o número de 'X' caracteres em todo o arquivo . O script abaixo imprime todo o arquivo novamente. Alguma sugestão?

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

Solução

Uma vez que esta é a revisão do código, vamos ir um por um:

#!/use/bin/perl

Essa linha shebang é mais provável um erro de digitação. Provavelmente deve ser

#!/usr/bin/perl

ou qualquer which perl retornos em seu sistema.

use strict;
use warnings;

Boa.

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

Não há necessidade de pacote filehandles globais quando você pode usar filehandles lexicais. A forma 3-argumento de open é preferível nos dias de hoje. Além disso, a mensagem de erro deve indicar o arquivo que você não podia abrir:

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

my @body = <FILE>;

Você está chupando o arquivo em uma matriz. Isso é completamente desnecessário neste caso.

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

declarar e inicializar (se necessário) todas as variáveis ??no menor espaço possível.

my $count;

O $string variável não é usado em qualquer outro lugar no seu código.

foreach $_(@body){

Isso é bobagem. for usa $ _ se nenhuma variável do laço é especificado. É mais fácil manter as coisas em linha reta, se você ao invés especificar uma variável de laço lexical.

for my $line ( @body ) {

No entanto, eu não acho que você deve ingerir o arquivo.

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

Isso resulta em um casamento bem-sucedido se a linha contém um X. Portanto, é equivalente a /X/. No entanto, isso não irá dizer-lhe a palavra que continha o 'X'. Para isso, você precisa decidir o que uma palavra é e fazer a sua correspondência ao nível da palavra.

Com tudo isso em mente, considere o seguinte script. Eu fiz uma hipótese simplificadora sobre o que eu considero ser uma palavra. Você deve ser capaz de construir sobre isso para satisfazer todos os 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__

UPDATE: Se você não se preocupam em encontrar as palavras dentro de cada linha que têm um ou mais caracteres X, o loop while seria simplificada:

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

usando $ _. Isso, no entanto, é provavelmente ineficiente (dado que estamos economizando cada personagem X combinado). Neste caso, tr funciona melhor:

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

Outras dicas

Você está imprimindo $_ em ambos os ramos da sua se-cláusula. Livrar-se do ramo mais.

Assumindo que "string" na sua pergunta é igual a "linha":

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top