Je veux que mon programme extrait des lignes d'un fichier contenant l'un des mots-clés d'un tableau, mais il n'affiche que le dernier mot-clé du fichier de mots-clés. Comment puis-je résoudre ce problème pour m'assurer qu'il trouve tous les mots clés?

use strict;
use warnings;

sub main {
    my $keywordFile = 'keyword.txt';
    open( keyWords, $keywordFile ) or die "$keywordFile not found\n";

    our @keywordArray = <keyWords>;
    while ( my $line = <keyWords> ) {
        push( @keywordArray, ($line) );
    }
    close(keyWords);

    my $fileName   = 'syslog.txt';
    my $outputFile = 'outputfile.txt';

    open( SysLog, $fileName ) or die "$fileName not found\n";
    open( my $fh, '>', $outputFile ) or die "$outputFile not found\n";

    while ( my $line = <SysLog> ) {
        foreach my $keyW (@keywordArray) {
            if ( $line =~ /$keyW/ ) {
                print "\n-------$keyW--------\n";
                print "$line";
                print $fh "$line";
            }
        }
    }
    close(SysLog);
    close $fh;
}

main();

print "\n";
0
Nafe 5 janv. 2016 à 19:25

3 réponses

Meilleure réponse

Le problème est que les chaînes de votre @keywordArray contiennent des retours à la ligne du fichier.

Vous devez utiliser chomp pour résoudre ce problème (et vous devez utiliser my de préférence à our) donc au lieu de

our @keywordArray = <keyWords>;
while ( my $line = <keyWords> ) {
    push( @keywordArray, ($line) );
}

Tu devrais écrire

my @keywordArray;
while ( my $line = <keyWords> ) {
    chomp $line;
    push @keywordArray, $line;
}

Ou mieux

chomp(my @keywordArray = <keyWords>);


Voici quelques éléments plus importants à surveiller

  • Les personnes familières avec Perl de haute qualité vous remercieront d'utiliser snake_case pour vos variables lexicales de base. CamelCase est généralement réservé aux identifiants globaux tels que les noms de packages

  • Il est bon que vous ayez utilisé la forme à trois paramètres de open, mais vous devriez également utiliser des descripteurs de fichier lexical . Vous avez utilisé un mélange de poignées lexicales et globales, ce qui est la pire option de toutes

  • Il n'est pas nécessaire de mettre l'ensemble de votre programme dans un sous-programme, puis de l'appeler. Ce n'est pas C

  • Si vous testez l'état d'un appel open et constatez qu'il a échoué, vous devez placer le contenu de la variable intégrée $! dans la chaîne die pour dire pourquoi l'ouverture a échoué. Il peut y avoir plusieurs raisons autres que le Fichier introuvable que vous avez codé. Mieux encore, vous pouvez activer autodie, qui vérifiera toutes les opérations de votre système de fichiers pour vous et générer une chaîne die appropriée

  • Il est très rare que les variables déclarées avec our soient utiles. Vous devriez toujours utiliser my sauf si vous avez une bonne raison d'avoir besoin d'une variable de package

  • @keywordArray = <keyWords> lit l'intégralité du fichier dans le tableau, le laissant à eof. La boucle suivante ne s'exécutera jamais car il n'y a plus rien à lire à partir du descripteur de fichier

2
Borodin 5 janv. 2016 à 17:44

Vous devez chomp les lignes pour supprimer les nouvelles lignes.

De plus, lire à partir d'un descripteur de fichier dans un contexte de liste

our @keywordArray = <keyWords>;

Lit le fichier entier, donc rien ne peut être lu dans ce qui suit

while ( my $line = <keyWords> ) {

Il est beaucoup plus rapide de créer une expression régulière à partir de tous les mots-clés que de faire correspondre chacun d'eux séparément:

#!/usr/bin/perl
use strict;
use warnings;

sub main {       
    my $keywordFile = 'keyword.txt';
    open $KW, $keywordFile or die "$keywordFile not found\n";
    chomp( my @keywords = <$KW> );
    my $keyword_regex = join '|', map quotemeta, @keywords;
    $keyword_regex = qr/($keyword_regex)/;

    my $fileName = 'syslog.txt';
    my $outputFile = 'outputfile.txt';

    open my $SL, $fileName or die "$fileName not found\n";
    open my $OUT, '>', $outputFile or die "$outputFile not found\n";

    while (my $line = <$SL>) {   
        if ($line =~ /$keyword_regex/) {
            print "\n-------$1--------\n";
            print "$line";
            print $OUT "$line";
        }
    }
    close $OUT;
}

main();
print "\n";
4
choroba 5 janv. 2016 à 16:43

Si vous faites référence au fait que le fichier de sortie ne contient que la dernière ligne qui correspond au mot-clé, c'est que vous ouvrez votre fichier de sortie pour l'écriture, ce qui signifie que vous écrasez tout ce que vous avez précédemment écrit. Vous devez l'ouvrir pour l'ajouter:

open(my $fh, '>>', $outputFile) or die "$outputFile not found\n";
-1
Tudor Crisan 5 janv. 2016 à 16:43