Comment dois-je imprimer un caractère particulier dans le fichier après avoir lu le fichier?

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

Question

Je suis en train de lire un fichier en utilisant un script perl. Ce fichier se compose de chaînes avec différents personnages et je suis censé identifier les chaînes contenant le caractère « X ». Je veux savoir comment dois-je (1) imprimer cette chaîne (contenant « X ») et aussi (2) écrire cette chaîne à un autre fichier (3) compter le nombre de « X » caractères dans le fichier entier . Le script affiche ci-dessous à nouveau l'ensemble du fichier. Toutes les suggestions?

#!/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;
Était-ce utile?

La solution

Puisque c'est la revue de code, nous allons aller un par un:

#!/use/bin/perl

Cette ligne de tralala est très probablement une faute de frappe. Il devrait probablement être

#!/usr/bin/perl

ou quel que soit le rendement which perl sur votre système.

use strict;
use warnings;

Bon.

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

Pas besoin de descripteurs de fichiers globaux de package lorsque vous pouvez utiliser des descripteurs de fichier lexical. La forme 3 argument de open est préférable ces jours-ci. En outre, le message d'erreur doit indiquer le fichier que vous ne pouviez pas ouvrir:

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

my @body = <FILE>;

Vous siphonage le fichier dans un tableau. C'est tout à fait inutile dans ce cas.

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

Déclaration et initialisation (si nécessaire) les variables dans la plus petite étendue possible.

my $count;

La $string variable est utilisée nulle part ailleurs dans votre code.

foreach $_(@body){

Ceci est stupide. for utilise $ _ si aucune variable de boucle est spécifiée. Il est plus facile de garder les choses directement si vous spécifiez une variable à la place de la boucle lexicale.

for my $line ( @body ) {

Cependant, je ne pense pas que vous devriez slurp le fichier.

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

Cela se traduit par un match réussi si la ligne contient un X. Ainsi, il est équivalent à /X/. Toutefois, cela ne vous dira pas le mot qui contenait le « X ». Pour cela, vous devez décider quel mot et faire votre correspondance au niveau des mots.

Avec tout cela à l'esprit, considèrent le script suivant. J'ai fait une hypothèse simplificatrice sur ce que je considère comme un mot. Vous devriez être en mesure de tirer parti pour satisfaire toutes les exigences:

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

Mise à jour: Si vous ne se soucient pas de trouver les mots dans chaque ligne qui ont un ou plusieurs caractères X, la boucle while serait simplifiée:

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

en utilisant $ _. Cela, cependant, est probablement inefficace (étant donné que nous économisons chaque correspondance caractère X). Dans ce cas, tr fonctionne le mieux:

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

Autres conseils

Vous imprimez $_ dans les deux branches de votre article si. Débarrassez-vous de la branche d'autre.

En supposant "string" dans votre question est égale à "ligne":

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;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top