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 :

Problème transfert fichier texte fichier .csv


Sujet :

Langage Perl

  1. #1
    Membre du Club
    Inscrit en
    Octobre 2007
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 99
    Points : 47
    Points
    47
    Par défaut Problème transfert fichier texte fichier .csv
    Bonjour à tout(e)s,

    Voici mon problème,

    Après avoir parsé une première fois un fichier texte pour y récupèrer certaines informations, j ai réussi à les écrire sur un autre fichier de sortie texte de cette forme :

    ------ Nouveau utilisateur -------
    ID : XXXXXXXX
    Nom : XXXXXXX
    Type : XXXXXX
    Dept : XXXXXX
    Dept2 : XXXXXX
    Division : XXXXXX
    Zone : XXXXXX
    Date : XXXXXX
    Modification : XXXXXX

    ------ Nouveau utilisateur --------
    etc etc

    Les X sont intentionnels pour un certain respect ! Il faut de plus préciser que chaque champ se trouve dans un tableau @ID, @Nom, @Type...
    Je voudrais maintenant mettre toutes ces données dans un fichier .csv
    Ainisi retrouver 9 colonnes et pour chaque ligne y insérer les informations.

    Pouvez vous m indiquer une piste pour débuter, car meme en lisant de la docs sur Text::CSV (par exemple) je suis bloqué!!

    Je pourrai par exemple ouvrir le fichier de sortie texte ou sont stockés les informations (XXXXXX) et les parser et créer un nouveau fichier .csv pour insérer ces dernières.

    Merci pour vos conseils...

  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 : 58
    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
    Points : 5 753
    Points
    5 753
    Par défaut
    Pour écrire un simple fichier CSV, il n'est pas d'une absolue nécessité d'utiliser le module Text::CSV.
    Si l'on considère que le séparateur de colonne sera stocké dans une variable $sep, voici une manière simple de réaliser l'opération (le fichier d'entrée est fourni sur l'entrée standard du script) :

    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
     
    use strict;
    use warnings;
     
    use feature qw(:5.10);
     
    my $sep = "\t";
    my %fields = ();
    while (defined(my $line = <STDIN>)) {
      chomp($line);
      my $in_user = ($line =~ /^------ Nouveau utilisateur -------$/) .. ($line =~ /^\s*$/);
      if ($in_user =~ /E0/) {
        # End of user
        say join $sep, map $_ // "", @fields{qw(ID Nom Type Dept Dept2 Division Zone Date Modification)};
        %fields = ();
      }
      elsif ($in_user > 1) {
        my ($name, $value) = split /\s*:\s*/, $line;
        $fields{$name} = $value;
      }
    }
    N'hésite pas à poser des questions pour comprendre.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  3. #3
    Membre éclairé
    Profil pro
    Assistant recherche bioinformatique
    Inscrit en
    Novembre 2007
    Messages
    877
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Assistant recherche bioinformatique

    Informations forums :
    Inscription : Novembre 2007
    Messages : 877
    Points : 835
    Points
    835
    Par défaut
    Bonjour,
    Ce que tu demandes est un des meilleurs roles de perl. Ceci est tres simple. On va commencer par se demander ce qu'est un fichier csv pour toi?
    Si c'est bien un fichier contenant des lignes de données séparées par un retour a la ligne. Et ou chaque ligne contient des données séparées par une virgule (Comma Separeted Values). Alors pour chaque données que tu auras parsées, il suffit de les ecrire dans ton fichier de sortie via :
    print SORTIE "$data1,$data2,data3\n";

    Z.

  4. #4
    Membre du Club
    Inscrit en
    Octobre 2007
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 99
    Points : 47
    Points
    47
    Par défaut
    Merci pour vos réponses !!!

    Cependant je ne comprend pas très bien le fonctionnement du programme...
    En effet un problème s ajoute : pour chaque nouveau utilisateur, le nombre de champs (ID, Nom,...) est différent.

    Mon fichier texte peut ressembler à ceci :

    ------ Nouveau utilisateur -------
    ID : XXXXXXXX
    Nom : XXXXXXX
    Type : XXXXXX
    Dept : XXXXXX
    Dept2 : XXXXXX
    Division : XXXXXX
    Zone : XXXXXX
    Date : XXXXXX
    Modification : XXXXXX

    ------ Nouveau utilisateur --------
    ID : XXXXXXXX
    Nom : XXXXXXX
    Type : XXXXXX
    Dept2 : XXXXXX
    Division : XXXXXX
    Zone : XXXXXX

    ------ Nouveau utilisateur -------
    ID : XXXXXXXX
    Type : XXXXXX
    Dept : XXXXXX
    Dept2 : XXXXXX
    Division : XXXXXX
    Zone : XXXXXX
    Date : XXXXXX

    ------ Nouveau utilisateur -------
    ID : XXXXXXXX
    Type : XXXXXX
    Division : XXXXXX
    Zone : XXXXXX
    Date : XXXXXX

    etc etc...
    Je n arrive donc pas a trouvé la logique pour recupérer les données et les transferer correctement dans un fichier .csv
    Je dois arriver au final à un tableau de 9 colonnes, le remplir et y mettre un champ vide pour chaque champ inexistant pour chaque utilisateur...

    Merci de votre aide précieuse

  5. #5
    Nouveau membre du Club Avatar de zanker
    Profil pro
    Consultant informatique
    Inscrit en
    Décembre 2011
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 23
    Points : 26
    Points
    26
    Par défaut
    Bonjour,

    dans le cas où tu génères ton fichier texte:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ------ Nouveau utilisateur -------
    ID : XXXXXXXX
    Nom : XXXXXXX
    Type : XXXXXX
    Dept : XXXXXX
    Dept2 : XXXXXX
    Division : XXXXXX
    Zone : XXXXXX
    Date : XXXXXX
    Modification : XXXXXX
     
    ------ Nouveau utilisateur --------
      ( ... )
    ceci avec ton script Perl qui utilise les variables de type liste: @ID, @Nom, @Type, @Dept, @Dept2, @Division, @Zone, @Date et @Modification.

    Tu peux créer, en fin de script, ton fichier CSV.
    Ca peut ressembler à ça avec ';' comme séparateur :
    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
    my $fichier_csv = 'monfichier.csv';
    open(my $fh_csv, '>'.$fichier_csv) or die "Erreur d'ouverture du fichier $fichier_csv : ".@!;
    print($fh_csv join(';', qw(ID Nom Type Dept Dept2 Division Zone Date Modification))."\n"); # Ligne d'entête du CSV
    for(my $num = 0; $num < scalar(@ID); $num++)
    {
    	print($fh_csv join(';',
    		($ID[$num],
    		$Nom[$num],
    		$Type[$num],
    		$Dept[$num],
    		$Dept2[$num],
    		$Division[$num],
    		$Zone[$num],
    		$Date [$num],
    		$Modification[$num])
    	)."\n");
    }
    Bien sûr, toutes les variables de type liste ont le même nombre d'éléments.

  6. #6
    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 : 58
    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
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par stansoad0108 Voir le message
    Cependant je ne comprend pas très bien le fonctionnement du programme...
    En effet un problème s ajoute : pour chaque nouveau utilisateur, le nombre de champs (ID, Nom,...) est différent.
    Justement, le script que je t'ai proposé tiens compte de l'absence de certains champs... il affiche toujours les colonnes ID Nom Type Dept Dept2 Division Zone Date Modification (et dans cet ordre).

    Mon fichier texte peut ressembler à ceci :
    Comme ton "tag" Nouveau utilisateur est légèrement différent entre les différents utilisateurs, j'ai un peu adapté le test de $in_user.
    De même, j'ai corrigé deux bugs (test $in_user > 1 et ajout de l'écriture du dernier utilisateur).
    La dernière version du script :

    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
    use strict;
    use warnings;
     
    use feature qw(:5.10);
     
    my $sep = "\t";
    my %fields = ();
    while (defined(my $line = <STDIN>)) {
      chomp($line);
      my $in_user = ($line =~ /^-+ Nouveau utilisateur -+$/) .. ($line =~ /^\s*$/);
      if ($in_user =~ /E0/) {
        # End of user
        say join $sep, map $_ // "", @fields{qw(ID Nom Type Dept Dept2 Division Zone Date Modification)};
        %fields = ();
      }
      elsif ($in_user && $in_user > 1) {
        my ($name, $value) = split /\s*:\s*/, $line;
        $fields{$name} = $value;
      }
    }
    say join $sep, map $_ // "", @fields{qw(ID Nom Type Dept Dept2 Division Zone Date Modification)} if %fields;
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  7. #7
    Membre du Club
    Inscrit en
    Octobre 2007
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 99
    Points : 47
    Points
    47
    Par défaut
    my $in_user = ($line =~ /^-+ Nouveau utilisateur -+$/) .. ($line =~ /^\s*$/);
    Je ne comprend pas cette ligne; que signifie les ..
    Dois je compléter avec les differents matchs ($line =~ /^ID:.+/)....

    if ($in_user =~ /E0/) {
    Quel est ce test?

    say join $sep, map $_ // "", @fields{qw(ID Nom Type Dept Dept2 Division Zone Date Modification)};
    Que signifie cette ligne ? Je n ai pas trouvé de réelles explications sur Internet....

    Je suis désolé, j ai encore du mal a comprendre l algo..
    Merci pour vos précisions

  8. #8
    Membre du Club
    Inscrit en
    Octobre 2007
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 99
    Points : 47
    Points
    47
    Par défaut
    say join $sep, map $_ // "", @fields{qw(ID Nom Type Dept Dept2 Division Zone Date Modification)};
    N y a t il pas d erreur de synthaxe? avec les // ?

    Cordialement

  9. #9
    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 : 58
    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
    Points : 5 753
    Points
    5 753
    Par défaut
    Citation Envoyé par stansoad0108 Voir le message
    Je ne comprend pas cette ligne; que signifie les ..
    Dois je compléter avec les differents matchs ($line =~ /^ID:.+/)....
    Non, il n'y a rien à compléter : les .. sont l'opérateur "flip-flop".
    Pour plus d'aide, tape :
    perldoc perlop (puis cherche "flip").

    Cet opérateur, utilisé dans un contexte scalaire, retourne 0 tant que le premier opérande est faux (sans tester le deuxième), et retourne 1, 2, 3... et ainsi de suite dès que le premier opérande est vrai et que tant que le deuxième est faux.
    Lorsque le 2e opérande devient vrai, il retourne le dernier indice en y ajoutant "E0" (ce qui, dans un contexte numérique, est équivalent à multiplier par 10 puissance 0, donc par 1 : cela ne change pas sa valeur numérique, mais ça modifie sa valeur chaine de caractère). Ensuite, il retourne à nouveau 0 tant que le premier opérande est faux, et ainsi de suite.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if ($in_user =~ /E0/) {
    Quel est ce test?
    Ce test permet de vérifier que l'on a atteint la deuxième condition du flip-flop (donc la fin d'un utilisateur).
    Il permet donc de traiter l'utilisateur que l'on a renseigné entre temps.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    say join $sep, map $_ // "", @fields{qw(ID Nom Type Dept Dept2 Division Zone Date Modification)};
    Que signifie cette ligne ? Je n ai pas trouvé de réelles explications sur Internet....
    Cette ligne affiche les colonnes d'une utilisateur, donc les valeurs sont stockées dans la table de hashage %fields.

    Pour permettre cela, je récupère d'abord la liste des colonnes ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @fields{qw(ID Nom Type Dept Dept2 Division Zone Date Modification)}
    Ici, l'opérateur qw() (perldoc perlop) permet de retourner un tableau de mots à partir d'une chaine donc les mots sont séparés par des espaces. Ces mots sont les noms des colonnes, qui ont servis de clés pour le hash %fields.
    Pour récupérer les valeurs de ces colonnes, il suffit d'utiliser @fields{@colonne_titles} (ici, @colonne_titles est directement fourni par qw(...)).
    Enfin, comme certaines valeurs peuvent être absentes pour certaines colonne, chaque valeur est pre-traitée par la fonction map, grâce à l'expression
    Cette expression utilise l'opérateur // (perldoc perlop) introduit dans perl 5.10.
    Cet opérateur est équivalent à :
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  10. #10
    Membre du Club
    Inscrit en
    Octobre 2007
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 99
    Points : 47
    Points
    47
    Par défaut
    Merci pour votre temps et vos explications !!!

    Je commence à comprendre, mais comment préciser que les informations stockées doivent être écrites dans le fichier de sortie .csv??

    Merci

  11. #11
    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 : 58
    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
    Points : 5 753
    Points
    5 753
    Par défaut
    La fonction say (à l'instar de print) écrit sur la sortie standard du script.
    Il suffit de rediriger la sortie du script dans un fichier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    perl script.pl > fichier.csv
    Autre moyen : ouvrir un fichier en écriture et écrire dedans :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    open my $CSV, ">", "fichier.csv" or die "Can't open fichier.csv en écriture: $!\n";
    ...
      say { $CSV } join $sep etc...
    ...
    Enfin, si j'ai bien compris la question.
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  12. #12
    Nouveau membre du Club Avatar de zanker
    Profil pro
    Consultant informatique
    Inscrit en
    Décembre 2011
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 23
    Points : 26
    Points
    26
    Par défaut
    Citation Envoyé par stansoad0108 Voir le message
    comment préciser que les informations stockées doivent être écrites dans le fichier de sortie .csv??
    L'ouverture du fichier CSV s'effectue avec la commande Perl open().
    Cette commande affecte un FILE HANDLE à la variable en premier paramètre de open().
    Puis, il suffit d'utiliser la commande print() en lui indiquant le FILE HANDLE précédemment ouvert avec open().
    Dans mon code, le FILE HANDLE correspond à la variable $fh_csv.

  13. #13
    Membre du Club
    Inscrit en
    Octobre 2007
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 99
    Points : 47
    Points
    47
    Par défaut
    Merci tout d abord...

    Sinon j ai testé pour les deux types de sortie (standart et fichier de sortie .csv)
    Malheureusement, en sortie standart (par exemple), il m affiche pour chaque ligne analysée "Use of uninitialized value $name in hash element at test.pl line 46, <INPUT> line 26232".

    Il écrit seulement la dernière ligne avec des informations (qui sont malheureusement incomplète) !!!

    Je n arrive pas à trouver le bug...
    Merci encore pour votre aide

  14. #14
    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 : 58
    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
    Points : 5 753
    Points
    5 753
    Par défaut
    C'est bien étrange, car dans le script que je t'ai fourni, il n'y a pas 46 lignes. Pourrais-tu poster ici le script qui bug ?

    Ensuite, je suppose que ton fichier d'entrée est gros. Pourrais-tu poster ici la ligne 26232 afin que l'on puisse analyser son contenu, et comprendre pourquoi la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my ($name, $value) = split /\s*:\s*/, $line;
    échoue à séparer le nom de la colonne de sa valeur...
    Plus j'apprends, et plus je mesure mon ignorance (philou67430)
    Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
    Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
    Si c'est utile, say

  15. #15
    Membre du Club
    Inscrit en
    Octobre 2007
    Messages
    99
    Détails du profil
    Informations forums :
    Inscription : Octobre 2007
    Messages : 99
    Points : 47
    Points
    47
    Par défaut
    Bonjour à tous,

    J'ai finalement réussi à manipuler le module Text::CSV pour parser mon fichier texte et écrire les informations dans un fichier .csv

    J'ai crée un tableau de 9 colonnes où les informations seront stockées. J ai préparé le fichier .csv avec les paramètres suivants:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    my $output_csv = Text::CSV->new ({ binary => 1, eol => "\n", sep_char => ","});
    $outuput_csv -> combine (("ID", ................, "Modification")); 
    print OUTPUT $output_csv -> string ();
    Je parse toutes les lignes. Je remplie mon tableau et je le print dans mon fichier csv à chaque fois que j en ai besoin.

    En tout cas, un GRAND merci pour vos aides et explications et surtout pour le temps que vous m'avez accordé!!!!!

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

Discussions similaires

  1. Problème serveur FTP-attribut fichier texte
    Par fabpeden dans le forum C
    Réponses: 1
    Dernier message: 26/05/2007, 03h59
  2. Réponses: 6
    Dernier message: 12/04/2007, 14h22
  3. problème lecture d'un fichier texte
    Par karimspace dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 02/03/2007, 08h55
  4. Problème listes chaînées et fichier texte
    Par khayyam dans le forum Pascal
    Réponses: 2
    Dernier message: 24/01/2007, 20h11
  5. Problème de réouverture de fichier texte
    Par EssaiEncore dans le forum Langage
    Réponses: 15
    Dernier message: 14/12/2005, 10h51

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