2009-06-09 10 views
0

Je lis un fichier en utilisant le script Perl. Ce fichier est constitué de chaînes avec des caractères différents et je suis supposé 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 dans un autre fichier (3) compter le nombre de 'X' caractères dans le fichier entier. Le script ci-dessous imprime à nouveau le fichier entier. Aucune suggestion?Comment devrais-je imprimer un caractère particulier dans le fichier après avoir lu le fichier?

#!/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; 
+1

Est-ce que ce travail est fait? –

+1

Je pensais la même chose, mais il pourrait tout aussi bien être un exemple de problème d'un texte d'introduction. – inkedmn

+1

À un certain point, vous devez ouvrir votre 'autre fichier' et vous assurer que vous écrivez dessus. Essayez également d'éviter d'utiliser cette forme d'ouverture. utilisez un formulaire qui retourne le handle de fichier à utiliser avec une variable $ régulière: open ($ fh, "filename"); ou l'une des variantes. –

Répondre

4

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

#!/use/bin/perl 

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

#!/usr/bin/perl 

ou quoi que ce soit which perl retourne sur votre système.

use strict; 
use warnings; 

Bonne.

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

Pas besoin de gérer les handles de fichiers globaux lorsque vous pouvez utiliser des handles de fichiers lexicaux. La forme de 3 arguments de open est préférable de nos jours. 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 complètement inutile dans ce cas. Déclarer et initialiser (si nécessaire) toutes les variables dans la plus petite portée possible.

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

my $count; 

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

foreach $_(@body){ 

C'est stupide. for utilise $ _ si aucune variable de boucle n'est spécifiée. Il est plus facile de garder les choses droites si vous spécifiez une variable de boucle lexicale.

for my $line (@body) { 

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

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

qui se traduit par une rencontre idéale si la ligne contient un X. Ainsi, il est équivalent à /X/. Cependant, cela ne vous dira pas le mot qui contenait le 'X'. Pour cela, vous devez décider ce qu'est un mot et faire votre correspondance au niveau du mot.

Avec tout cela en tête, considérez le script suivant. J'ai fait une hypothèse simplificatrice concernant ce que je considère être un mot.Vous devriez être en mesure de construire sur ce 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é:

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

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

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

Je suis d'accord avec tous vos commentaires. Cependant, le point 3 de la question demande "compter le nombre de 'X' caractères dans le fichier entier". Votre solution, à la place, compte le nombre de mots (chaînes qui dépendent de la définition de "chaînes") qui contiennent un caractère "X". – user55400

+0

@blixtor: Merci d'avoir rattrapé ça. Bien sûr, chaque mot peut contenir plusieurs caractères X. En fait, je me rends maintenant compte que l'OP ne se souciait pas de diviser les lignes en mots, etc. –

+0

La forme d'ouverture à 3 arguments est parfois utile et parfois non. Il est facile de toujours utiliser 2 arguments ouverts en toute sécurité, et parfois vous voulez avoir la possibilité de prendre des couches d'E/S par défaut à partir du pragma ouvert ou du commutateur -C. Si vous allez critiquer l'ouverture de 2-arg, dites au moins "parce que vous pouvez utiliser un nom de fichier de variable un jour", et pas seulement "c'est la nouvelle façon de le faire". – ysth

1

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

+0

Il peut ne pas être évident pour un nouveau venu que «imprimer»; imprime '$ _', mais c'est ce qui arrive. –

+0

exactement. J'aurais pu être un peu plus verbeux. Pardon. – innaM

0

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; 
Questions connexes