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 :

Regex perl (test \n)


Sujet :

Langage Perl

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 19
    Points : 11
    Points
    11
    Par défaut Regex perl (test \n)
    Bonjour,

    J'ai un fichier qui se compose comme cela :

    Type de document Ouvrage
    Thème ARCHITECTURE
    Titre Symboles et décors des maisons villageoises : marques sociales, protections magiques
    Auteurs FILLIPETTI Hervé
    isbn 2-84038-219-9
    Référence Rustica
    Commentaire fgsdfgsdfggggfdgfssdfg
    sdfgdsfgdsfgsd
    sdfgdfgs
    Numéro 121
    Titre2 test


    Toutes mes lignes commencent pas des "intitulés de champs", malheureusement dans le champ commentaire il y arrive qu'il y ait des retour à la ligne. J'ai un script qui interpret ses retour à la ligne comme des chagements de champs. Je voudrais donc supprimer tout les \n qui ne sont pas suivit d'un intitulé(Auteurs,isbn,Numéro...).

    Je ne connais vraiment pas grand chose à Perl et je ne vois aps comment mettre en forme mon idée.


    Je pensais à

    récupéré les saut de lignes et le mot suivant avec un /(\n)(.*\s)/

    Puis tester si $2 etait dans ma liste de champs(Auteurs,isbn,Numéro...).
    Si c'est le cas je ne fais rien sinon je fais un s/$1$2//g.


    Je ne sais pas si cette solution est correcte, en tout cas si elle l'est je ne vois aps comment appliquer ca en perle, quelqueu pourrait m'aideR?

    Merci!


    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
     
    #!/usr/bin/perl
     
    open(FH, 'fichiertest.txt');
    my $content;
    $content .= $_ while (<FH>);
    close(FH);
     
    my $condition = '(\n)(\p{L}*)';
    my $champok = 1;
    my @montableau_de_champ = ("Titre","Numéro","Auteurs");
     
    while ( $content =~ /$condition/)
    {
    	foreach $mavar (@montableau_de_champ)
    	{
    		if ($2 == $mavar)
    		{
    			$champok=0;
    		};
    	}
    	if ( $champok == 1 )
    	{
    		$content =~ s/$1$2//;
    	} 
    }

  2. #2
    Membre confirmé Avatar de iblis
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 57

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Points : 570
    Points
    570
    Par défaut
    Bonsoir.

    Je ne sais pas trop ce que tu veux faire de ton fichier de bibliographie (issu de Francis ?): le convertir vers BibTeX ou EndNote, le classer ?

    Dans tous les cas, tu n'as pas besoin de le modifier pour gèrer des champs multilignes. Tu peux par exemple faire une gestion d'états (pour s'avoir quand tu passes à un nouvel enregistrement et quand tu passes à un nouveau champ), ou encore alors lire engegistrement par enregistrement (en modifiant localement $/) et parser les champs avec des regex en multiligne.

    En attendant si veux supprimer les \n dans les champs tu peux faire comme suit :

    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
     
    use strict; use warnings;
    use List::MoreUtils qw(any);
     
    my @field_marks = qw(Type Thème Titre Auteurs isbn Référence Commentaire Numéro Titre2);
     
    open my $fh, '<', 'file.txt'
    	or die "$!\n";
     
    while (<$fh>) {
    	chomp;
    	my $first = (split /\s+/)[0];
    	print "\n" if not defined $first or any { $first eq $_ } @field_marks;
    	print;
    }
    print "\n";
    Le principe est d'imprimer les lignes sans le "\n" de fin et de n'imprimer celui-ci que si la ligne suivante commence par un marqueur de champ.

    Commentaires :

    1. Il est indispensable d'utiliser les pragmas strict et warnings pour éviter les bourdes les plus élémentaires.

    2. Je te conseille de ne pas utiliser de filehandle nu mais une variable locale pour les stocker (comme dans l'exewmple).

    3. Le chomp supprime le "\n" en fin de ligne lu (en fait supprime les caractères de fin ayant pour valeur $/, le séprateur d'enregistrement lus en entrée, par défaut "\n");

    4. $first contient le premier mot de la ligne.

    5. any est une fonction de List:MoreUtils qui retourne vrai si pour au moins un éléments de la liste le block est évéalué vrai.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 19
    Points : 11
    Points
    11
    Par défaut merci
    Cool merci, enfaite tu prends la solution dans l'autre sens. Ce je voulais faire n'était pas possible? ou juste mauvais ?

    Ce fichier est un export d'Alexandrie v5.

    Enfaite je dois le faire passer a un de mes clients pour qu'il le transforme en unimarc.
    Leur moulinette qui fait le passage en unimarc ne doit pas utiliser "la gestion d'état" donc ils ont eu un problème sur l'importe pour quelques notices.

    Je vais tester ton script (essayer de le comprendre :-). Merci pour les commentaires.

    Je te tiens au courant, j'attends de recevoir mes bouquins perl et je rentre serieusement dedans.

    a+++


    ps = J'avoue que j'ai un peu de mal avec toutes ces commandes genre chomp et print qui vont prendre en entrée standard les valeurs de retour du while etc.. Il faut que je m'habitue. Ca n'aide pas la lecture pour els non avertits

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    j'ai teste, mais cela ne marche pas car j'ai pas mal d'intitule de champs compose de plusieurs mot, j'ai tente d'adapter le script, avec un delimiter tab pour le split.

    Mais cela ne semble pas marcher...

    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
     
    #!/usr/bin/perl
     
    use strict; use warnings;
    use List::MoreUtils qw(any);
     
    my @field_marks = qw("Type" "Thème" "Titre" "Auteurs" "isbn" "Référence" "Commentaire" "Numéro" "Année de parution" "Nbre d'exemplaires" "Emprunt autorisé" "Nbre de jrs emprunt" "Cote" "Prix" "Date d'indexation" "Langue" "Localisation" "Descriptif du contenu" "Descripteurs" "édition");
     
    open my $fh, '<', 'fichiertest.txt'
            or die "$!\n";
     
    while (<$fh>) {
            chomp;
            my $first = (split /\t+/)[0];
            print "\n" if not defined $first or any { $first eq $_ } @field_marks;
            print;
    }
    print "\n";
    j'ai mis le fichier sur lequel je fais des tests en attachement...

    merci encore

    ps=je comprend pas trop les types de sauts de lignes des fichier? fichiertest = windows? script = linux?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    julien@port-ber:~/script-perl$ ./saut-ligne.pl >toto
    julien@port-ber:~/script-perl$ file toto 
    toto: UTF-8 Unicode text, with CRLF, CR line terminators
    julien@port-ber:~/script-perl$ file fichiertest.txt
    fichiertest.txt: UTF-8 Unicode text, with CRLF line terminators
    Fichiers attachés Fichiers attachés

  5. #5
    Membre confirmé Avatar de iblis
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 57

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Points : 570
    Points
    570
    Par défaut
    La fonction qw(STRING) (pour quote word) retourne une liste dont chaque élément est un mot extrait de la chaîne en argument. Elle permet de définir rapidement une liste composée de mots, sans quoter chacun des mots un par un.

    Pour définir une liste en toute généralité :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    my @fields = ('un champs', 'un autre champs');
    Toutefois, tel quel le script que je t'ai proposé en exemple se base sur le premier mot pour déterminer si une ligne comporte un marqueur de champ, ce qui est suffisant si tes marqueurs de champs de risquent pas de correspondre à un mot dans les champs que tu nettoies. Donc il te suffit de rajouter à la liste les premiers mots de tes autres marqueurs de champs.

    Je te conseille de parcourir la FAQ Perl sur ce site, elle est très bien faite et te donnera les éléments nécessaires pour débuter (et au-delà).

    La conversion vers Unimarc n'est jamais très simple mais certainement bien plus plus que de parser du Unimarc non-trivial. Regarde les modules Marc sur le CPAN, en particulier Marc::Record.

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 19
    Points : 11
    Points
    11
    Par défaut merci
    merci.

    Mais cela ne semble pas marcher :-(

    Avant :

    Type de document Jeu
    Thème RECYCLAGE
    Titre Le jeu des sept familles
    Auteurs SICTOM
    Référence SICTOM
    Année de parution 2000
    Descripteurs RECYCLAGE
    Commentaire Un jeu pour apprendre à trier
    les déchets en
    s'amusant ! Des illustrations vivantes, drôles et colorées.
    Nbre d'exemplaires 1
    Emprunt autorisé oui


    apres


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    julien@port-ber:~/script-perl$ ./sautligne.pl 
    
    Type de document	Jeu
    Thème	RECYCLAGE
    Titre	Le jeu des sept familles
    Auteurs	SICTOM
    Référence	SICTOM
    Année de parution	2000
    Descripteurs	RECYCLAGE
    s'amusant ! Des illustrations vivantes, drôles et colorées.
    Nbre d'exemplaires	1
    Emprunt autorisé	oui
    Enfaite j'ai essaye d'utiliser tout le champ car sinon quand le script fait un split sur le champ espace cela risque de ne pas marcher non?

    En tout cas la j'ai des lignes qui sautes(a cote de ?RECYCLAGE) je ne comprends pas pourquoi...

  7. #7
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Voici une approche toute différente
    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
    #!/usr/bin/perl
     
    use strict;
    use warnings;
     
     
    open my $fh, '<', 'test.txt'
    	or die $!;
    my @text = <$fh>;
    close $fh;
     
    # $text contient l'entièreté du texte, séparation des lignes par le tag $$
    my $text = join ('$$', @text);
     
    # suppression des enters : tout le texte sur une seule ligne, différentes phrases séparées par $$
    # $text contient : Type de document	Jeu $$Thème	RECYCLAGE $$Titre	Le jeu des sept familles
    $text =~ s/\n/ /g;
     
    # $texte contient donc 2 types de lignes à récupérer
    # champ\tvaleur$$                       (champ uniligne du texte d'origine)
    # champ\tvaleur$$valeur$$valeur$$       (champ multiligne du texte d'origine)
     
    # traitement des champs unilignes du texte d'origine
    # recherche du motif caractères\tcaractères$$ (uniquement les champs unilignes du texte d'origine)
    # suppression des $$ et mise d'un enter
    $text =~ s/([^\t]+\t[^\t]+)\$\$/$1\n/g;
     
    # traitement des champs multilignes du texte d'origine
    # il ne reste donc plus que des $$ dans les commentaires qui étaient sur plusieurs lignes dans le texte original
    # $text contient donc 
    # Descripteurs	RECYCLAGE (= champ uniligne déjà traité)
    # Commentaire	Un jeu pour apprendre à trier $$les déchets en $$s'amusant ! Des illustrations vivantes, drôles et colorées. (= champ multiligne à traiter)
    # Nbre d'exemplaires	1 (= champ uniligne déjà traité)
     
    # suppression des derniers $$
    $text =~ s/\$\$//g;
     
    print $text."\n";


    $text contient au final
    Type de document Jeu
    Thème RECYCLAGE
    Titre Le jeu des sept familles
    Auteurs SICTOM
    Référence SICTOM
    Année de parution 2000
    Descripteurs RECYCLAGE
    Commentaire Un jeu pour apprendre à trier les déchets en s'amusant ! Des illustrations vivantes, drôles et colorées.
    Nbre d'exemplaires 1
    Emprunt autorisé oui
    Nbre de jrs emprunt 21
    Cote PO.4.1-SIT
    Prix 0
    Numéro 4
    Date d'indexation 21/09/2000
    Thème RECYCLAGE
    Langue Français
    Titre ,
    Localisation Maison de la Nature et de l'Environnement de l'Isère
    Descriptif du contenu 44 cartes à jouer
    Type de document CD ROM
    Thème FORET
    Titre Une forêt dans la tête : la forêt européenne, plaines et collines
    Auteurs DEFLANDRE Guy,GERARD Pierre
    Référence IMédia
    Année de parution 1996
    Descripteurs FORET,MILIEU FORESTIER
    Nbre d'exemplaires 1
    Emprunt autorisé oui
    Nbre de jrs emprunt 21
    Cote RV.5.1-DEF
    Prix 0
    Numéro 5
    Date d'indexation 21/09/2000
    N° édition Troisième édition
    Thème FORET
    Langue Français
    Titre ,adulte ou plus de 10 ans
    Localisation Maison de la Nature et de l'Environnement de l'Isère
    Type de document Ouvrage
    Thème ARCHITECTURE
    Titre Symboles et décors des maisons villageoises : marques sociales, protections magiques
    Auteurs FILLIPETTI Hervé
    isbn 2-84038-219-9
    Référence Rustica
    Année de parution 1997
    Descripteurs ARCHITECTURE
    Commentaire Quelle signification attribuer aux signes que portent de nombreuses maisons villageoises et qui passent souvent inaperçus sinon une valeur symbolique ?
    nb : les commentaires sont bien sur une seule ligne, c'est l'affichage sur le forum qui les fait apparaître sur plusieurs lignes.
    -- Jasmine --

  8. #8
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Une autre façon d'obtenir le même résultat en lisant le fichier ligne par ligne

    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
    #!/usr/bin/perl
     
    use strict;
    use warnings;
     
     
    open my $fh, '<', 'test.txt'
    	or die $!;
    while (<$fh>) {
          chomp;
          if($. == 1){
            # évite un saut de ligne pour la première ligne
            print $_;
          }
          elsif (/\t/){
            # si il y a un \t c'est que l'on doit commencer sur une nouvelle ligne
            print "\n".$_;
          }
          else{
            # tant qu'on n'a pas un \t on continue d'écrire sur la ligne précédente
            print $_;
          }
    }
    close $fh;
    -- Jasmine --

  9. #9
    Membre confirmé Avatar de iblis
    Inscrit en
    Janvier 2007
    Messages
    510
    Détails du profil
    Informations personnelles :
    Âge : 57

    Informations forums :
    Inscription : Janvier 2007
    Messages : 510
    Points : 570
    Points
    570
    Par défaut
    L'exemple que je t'ai donné est fonctionnel sur ton exemple de départ (par acquis de ton conscience je teste toujours le code que je poste) mais la solution de Jasmine te montre une autre façon de faire, ce qui est le but — plutôt que de te fournir du code.

  10. #10
    Membre émérite
    Avatar de Jasmine80
    Femme Profil pro
    Bioinformaticienne
    Inscrit en
    Octobre 2006
    Messages
    3 157
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 44
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Bioinformaticienne
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2006
    Messages : 3 157
    Points : 2 673
    Points
    2 673
    Par défaut
    Il est peut-être préférable de ne pas utiliser de liste précise de champs afin que le code puisse être utilisé sur des cas plus généraux.
    -- Jasmine --

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 19
    Points : 11
    Points
    11
    Par défaut merci
    Merci

    Cela marche nickel.

    L'approche etait differente et comme tu le dis peut s'appliquer a des cas plus general.

    Merci a tout les 2 pour votre aide, j'ai appris pas mal de chose.

    Merci encore

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

Discussions similaires

  1. regex perl difficile
    Par Eric5959 dans le forum Langage
    Réponses: 16
    Dernier message: 30/09/2009, 10h14
  2. Réponses: 2
    Dernier message: 28/06/2008, 22h52
  3. class Regex (un test)
    Par Rukia dans le forum C#
    Réponses: 10
    Dernier message: 05/03/2008, 10h26
  4. [Regex perl] Matcher un gros fichier
    Par osoumayaj dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 18/01/2007, 09h37
  5. [PERL]le test ?:
    Par LE NEINDRE dans le forum Langage
    Réponses: 5
    Dernier message: 24/08/2005, 13h02

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