IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Perl Discussion :

Création fichier CSV avec incrémentation des arguments dans les cellules


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 198
    Par défaut Création fichier CSV avec incrémentation des arguments dans les cellules
    Bonjour,

    je fais du perl tous les 36 du mois et je me décide à solliciter de l'aide pour 2 problèmes.

    J'ai plusieurs fichiers CSV (mis 4 fichiers au format .XLS) dont le nom contient le protocole TCP ou UDP ainsi que le numéro du port. Le contenue du fichier à les adresses IP utilisant ces ports.

    J'ai fait un script lisant tous les format CSV d'un répertoire:
    -affiche => @IP protocole port
    -affiche le nombre de fois qu'une adresse IP apparaît
    -crée un fichier CSV contenant par ligne l'@IP protocole port (voir ci-dessous un bout)


    10.221.166.1 TCP 135
    10.235.95.97 TCP 12443
    10.221.166.1 TCP 135
    10.221.166.1 TCP 139
    10.235.125.100 TCP 135
    10.221.166.1 UDP 123
    10.221.166.1 UDP 137


    Je ne peux pas utiliser les modules à causes du proxy au travail.

    Objectif 1

    Que le fichier traite par ligne tous les ports et protocole utilisé par une adresse IP pour arriver à quelque chose comme ceci. Si on peut être fainéant et éviter d'autant des erreurs

    10.221.166.1 TCP_135_139 UDP_123_137

    Ca évite d'avoir autant de ligne que de port.

    les underscore sont utilisé pour éviter des problèmes d'interprétation avec les virgules ou points virgules.

    Objectif 2

    Mettre dans la première ligne du fichier CVS pour faire des tries sans perdre une ligne
    Cellule 1 => Adresse
    Cellule 2 => Protocole
    Cellule 3 => Port


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    #!/usr/bin/perl
    use strict;
    use warnings;
    use DateTime;
     
    my $dt = DateTime->now (time_zone=>'Europe/Paris');
    my $ymd = $dt->ymd;
    my $hms = $dt->hms('-');
     
     
    my @all = glob 'C:\Users\Alexandre\Documents\PERL_scripts\GARENCE\*.csv';
     
    # Ces variables sont crées en dehors des boucles pour les utiliser dans et en dehors des boucles.
    	my @ligne;
    	my @IP;
    	my $word;
    	my %count;
     
    foreach my $fichier (@all) {
     
    	# Récupére les chiffres du nom du fichier qui correspondant au numéro de port	
    	my @port = $fichier =~ m/\d+/g;
     
    	# Récupére dans le nom du fichier le nom TCP ou UDP
    	my @protocole = $fichier =~ m/(TCP|UDP)/ig;
     
     
    	open my $CSV, '>>', "syntheseCSV\-$ymd\-$hms\.csv";
    	open my $fh, '<', $fichier;
     
     
    		while (<$fh>) {
    			chomp;
     
    			# Fait un split sur "," et ";" et ne place que l'élément 0 dans @ligne
    			my @ligne = (split /[,;]/)[0];
     
    			# Ne traite pas les lignes qui contiennent une lettre majuscule ou minuscule
    			next if /[a-zA-Z]/;
     
    			#Affiche les éléments qui seront inclus dans le fichiers CSV
    			print "$ligne[0]\t @protocole\t @port \n";
     
    			#Envoie les données au fichier CSV
    			print $CSV "$ligne[0]\,@protocole\,@port\n";
     
    			# Ajoute la valeur de @ligne à @IP
    			push @IP, @ligne;
     
     
    			}
    		}
     
    			print "\n";
     
    	foreach $word (@IP) {
    $count{$word} += 1;
    }
    # Trie par ordre décroissant des valeurs
    foreach $word (sort { $count{$b} <=> $count{$a} } keys %count) {	
    print "$word\t existe $count{$word} fois\n";
    }
    Je suis preneur de toute idée

    Fichiers attachés Fichiers attachés

  2. #2
    Expert confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    3 577
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2009
    Messages : 3 577
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    			# Fait un split sur "," et ";" et ne place que l'élément 0 dans @ligne
    			my @ligne = (split /[,;]/)[0];
    Dans cette ligne, tu récupères un élément (un scalaire donc) et tu le places dans un tableau (@IP)... c'est plutôt inutile et génère une ambiguité à la lecture (on pense que tu récupères plusieurs éléments).
    Pourquoi ne pas écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my $ligne = (split /[,;]/)[0];
    Et puis, autant donner un nom "significatif" à $ligne, car là, on se sait pas ce que contient $ligne (une IP ? un port ? un protocole ?)

    Ensuite, cette ligne
    est placée après le split. Elle pourrait être placée avant, vu que la recherche de motif opère sur $_ et pas sur @ligne. A moins que tu voulais qu'elle n'opère sur @ligne ?

    Enfin, je ne vois pas très bien où tu récupères la ligne des ports pour chaque IP ?!

    En tout cas, pour faire ce genre de chose, je verrais bien l'usage d'une hash de hash de array, dans le style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    %IP = ( 127.0.0.1 => { UDP => [155, 156 ], TCP => [ 241, 246] } );

  3. #3
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 198
    Par défaut
    Merci pour ces débuts de pistes.

    je ne vais pas avoir le temps de tester de tester cet après midi mais déjà oui utiliser une scalare semble logique, je ne suis plus pourquoi j'étais passer pas un array.
    Le nom je l'avais mis un vite fait car j'étais en plein tests pour arriver à un début de quelque chose.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my $ligne = (split /[,;]/)[0];
    Mettre en début de boucle ca semble tellement logique ...


    Enfin, je ne vois pas très bien où tu récupères la ligne des ports pour chaque IP ?!
    Les ports pour le coup ne sont dans les fichiers mais dans le nom qui m'ont été fournis donc je les récupères dans le nom du fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    my @all = glob 'C:\Users\Alexandre\Documents\PERL_scripts\GARENCE\*.csv';
    foreach my $fichier (@all) {
         my @port = $fichier =~ m/\d+/g;
         .....
         }

    Pour le hash de hash, j'avoue ne pas connaître, je vais me pencher sur le sujet

    En tout cas, pour faire ce genre de chose, je verrais bien l'usage d'une hash de hash de array, dans le style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    %IP = ( 127.0.0.1 => { UDP => [155, 156 ], TCP => [ 241, 246] } );
    Je te tiendrais au courant.

  4. #4
    Rédacteur/Modérateur

    Avatar de Lolo78
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mai 2012
    Messages
    3 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2012
    Messages : 3 612
    Billets dans le blog
    1
    Par défaut
    Je pense aussi pour un hash de hashes de tableauxs.

    Avec par exemple ces données:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    10.221.166.1 TCP 135
    10.221.166.1 TCP 139
    10.235.125.100 TCP 135
    10.221.166.1 UDP 123
    10.221.166.1 UDP 137
    Tu pourrais essayer ceci (pas testé, je sur sur une tablette sans Perl):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    my %ips; # le hash
    while (<DATA>) {
        chomp;
        my ($ip, $protocole, $port) = split;
        push @{$ips{$ip}{$protocole}}, $port;
    }
    Ce qui devrait donner à peu près une structure équivalente à ceci.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    %ips = ( 10.221.166.1 => { UDP => [123, 1337 ], TCP => [ 135, 139] } ,
                 10.235.125.100 => { TCP => [135]},
              );
    Une fois une telle structure remplie, afficher tes données au format souhaité devient très simple. Mais n'hésite pas à demander si tu éprouves des difficultés.

  5. #5
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 198
    Par défaut
    Re !

    J'ai mis un peu d'ordre suivant les recommandations de Philou sur l'utilisation de scalar en place de de array pour simplifier ainsi que le changement de position du next if.

    Tout fonctionne comme avant.

    Ca donne ca

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    use strict;
    use warnings;
    use DateTime;
     
    my $dt = DateTime->now (time_zone=>'Europe/Paris');
    my $ymd = $dt->ymd;
    my $hms = $dt->hms('-');
     
     
    my @all = glob 'C:\Users\Alexandre\Documents\PERL_scripts\GARENCE\*.csv';
     
    # Ces variables sont crées en dehors des boucles pour les utiliser dans et en dehors des boucles.
    	#my @ligne;
    	my $ip;
    	my @IP;
    	my $word;
    	my %count;
            my %ips;
     
     
    foreach my $fichier (@all) {
     
    	# Récupére les chiffres du nom du fichier qui correspondant au numéro de port	
    	my ($port) = $fichier =~ m/\d+/g;
     
    	# Récupére dans le nom du fichier le nom TCP ou UDP
    	my ($protocole) = $fichier =~ m/(TCP|UDP)/ig;
     
     
    	open my $CSV, '>>', "syntheseCSV\-$ymd\-$hms\.csv";
    	open my $fh, '<', $fichier;
     
     
    		while (<$fh>) {
    			chomp;
     
    			# Ne traite pas les lignes qui contiennent une lettre majuscule ou minuscule
    			next if /[a-zA-Z]/;
     
    			# Fait un split sur "," et ";" et ne place que l'élément 0 dans @ligne
    			my $ip = (split /[,;]/)[0];
     
    			#Affiche les éléments qui seront inclus dans le fichiers CSV
    			print "$ip\t $protocole\t $port \n";
     
    			#Envoie les données au fichier CSV
    			print $CSV "$ip\,$protocole\,$port\n";
     
    			# Ajoute la valeur de $ligne à @IP
    			push @IP, $ip;
     
    			push @{$ips{$ip}{$protocole}}, $port;			
     
    			}
    		}		
     
    			print "\n";
     
    	foreach $word (@IP) {
    $count{$word} += 1;
    }
    # Trie par ordre décroissant des valeurs
    foreach $word (sort { $count{$b} <=> $count{$a} } keys %count) {	
    print "$word\t existe $count{$word} fois\n";
    }

    En lisant Lolo et son exemple, je comprend que l'on peut avoir un hash avec une clé unique qui peut elle même avoir des sous clés unique avec chacune des valeurs.

    Sur ton exemple je ne devrais utiliser que la ligne push vu que $protocole et $port sont dans la boucle foreach avant. Les fichiers CSV ne contiennent que les adresses IP.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    my %ips; # le hash
    while (<DATA>) {
        chomp;
            push @{$ips{$ip}{$protocole}}, $port;
    }

    Je crois avoir deviné l'idée de la ligne ....
    push @{$ips{$ip}{$protocole}}, $port;

    Mais comment l'utiliser pour ressortir les informations au format voulu?
    Une fois le hash remplis je pourrais supprimer la ligne suivante pour le création du fichier CSV finale:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print $CSV "$ip\,$protocole\,$port\n";
    mais comment le remplacer avec les informations du hash ?

    je brûle ?

  6. #6
    Membre confirmé
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 198
    Par défaut
    J'ai trouvé sur ce lien un exemple pour afficher le hash de hash
    http://perlmaven.com/multi-dimensional-hashes

    Ce moyen en fin de script

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    foreach my $cle ( keys %ips) {
        foreach my $souscle (keys %{ $ips{$cle} }) {
            print "$cle, $souscle: $ips{$cle}{$souscle}\n";
        }
    }
    mais le résultat n'est pas encore au point

    10.235.108.8, TCP: ARRAY(0x2b9e520)
    10.92.28.77, UDP: ARRAY(0x2b07000)
    10.92.28.136, UDP: ARRAY(0x2b05cd8)
    10.92.28.152, UDP: ARRAY(0x2b077e0)
    10.246.0.11, TCP: ARRAY(0x2b9d678)
    10.235.111.171, TCP: ARRAY(0x2b9dbb8)
    10.92.28.163, UDP: ARRAY(0x2b07228)
    10.59.58.230, UDP: ARRAY(0x2b05838)
    10.59.58.230, TCP: ARRAY(0x2b9e1d0)


    pas de valeurs et deux lignes pour la même adresse IP avec protocole différent.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. ajouter des combobox dans les cellules de stringgrid
    Par sky88 dans le forum Débuter
    Réponses: 5
    Dernier message: 22/01/2009, 18h35
  2. DataGridView et format des valeurs dans les cellules
    Par saultapt dans le forum Windows Forms
    Réponses: 5
    Dernier message: 17/06/2008, 16h55
  3. Afficher des Couleurs dans les Cellules automatiquement
    Par dreams11 dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 04/11/2007, 22h17
  4. Réponses: 3
    Dernier message: 04/04/2007, 14h18
  5. JTable avec des JPanel dans les cellule
    Par pigpen dans le forum Composants
    Réponses: 11
    Dernier message: 13/04/2006, 19h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo