Como devo imprimir um caráter particular no arquivo depois de ler o arquivo?
-
13-09-2019 - |
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;
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;