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 :

Suppression d'un "caractère"


Sujet :

Langage Perl

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2008
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 20
    Par défaut Suppression d'un "caractère"
    Bonjour,

    Alors voilà j'ai un petit problème et je viens quémander de votre aide !

    J'ai un fichier lettre.txt qui possède une certaine mise en forme.
    Je souhaiterais supprimer les retours chariots, virguiles, tirets, etc...

    pour avoir un texte de cette forme:
    Cher ami++Je suis toute émue de vous dire que j'ai bien compris l'autre jour que vous aviez toujours une envie folle de me faire danser. Je garde le souvenir de votre baiser et je voudrais bien que ce soit une preuve que je puisse être aimée par vous. Je suis prête à montrer mon affection toute désintéressée et sans cal- cul et si vous voulez me voir ainsi vous dévoiler sans artifice mon âme toute nue daignez me faire visite nous causerons et en amis franchement je vous prouverai que je suis la femme sincère capable de vous offrir l'affection la plus profonde comme la plus étroite amitié en un mot : la meilleure épouse dont vous puissiez rêver. Puisque votre âme est libre pensez que l'abandon ou je vis est bien long bien dur et souvent bien insupportable. Mon chagrin est trop gros. Accourrez bien vite et venez me le faire oublier. À vous je veux me sou- mettre entièrement. Votre poupée
    J'ai deux problème:
    - Je vois pas d'où viens le double espace (là où j'ai mis le ++)
    - J'arrive pas à supprimer le "- " (-\s).

    Voici mon code:
    while(my $ligne = <LECTURE>){
    chomp($ligne);
    $ligne =~ s/\s+/ /g;
    $ligne =~ s/-\s+//g;
    $ligne =~ s/(\s+)?,(\s+)?/ /g;
    print ECRITURE $ligne;
    }
    Voilà si quelqu'un pouvait m'aider, merci.

  2. #2
    Membre Expert
    Avatar de Woufeil
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 1 076
    Par défaut
    Bonjour,

    Pour le ++, je ne vois pas pourquoi à première vue, mais pour le tiret le problème est simple : ta regex supprime tout ce qui ressemble à - plus au moins un espace, hors ton tiret est en fin de ligne et tu supprimes les sauts de ligne avec chomp, donc tu te retrouve avec une fin de chaine qui est cal- sans espace après le tiret, elle n'est donc pas matchée par la regex

  3. #3
    Membre chevronné
    Avatar de Schmorgluck
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    371
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2006
    Messages : 371
    Par défaut
    Les deux problèmes ont la même cause : même si tu supprime le retour chariot, tu traites toujours tes lignes une par une. Par conséquent, la virgule à la fin de ta première ligne est transformée en espace, de même que les espaces au début de ta deuxième : deux espaces consécutifs à l'affichage. Pour la même raison, ta regex /-\s+/ ne reconnait rien dans le texte. La ligne qui se termine par un tiret... ben, se termine par un tiret, quoi, sans espace derrière.

    Je pense que la meilleure solution serait de passer par un "slurp", c'est à dire charger tout le fichier dans une seule chaîne avant le traîtement. En tout cas, c'est la solution la plus simple : j'ai beau chercher, les autres possibilités qui me viennent à l'esprit sont plutôt alambiquées.

    Pour faire le "slurp" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    do
    {
      local $/;
      $_=<LECTURE>;
      s/\s+/ /g;
    # "\s*" est en pratique équivalent et préférable à "(\s+)?", sauf besoin de capture.
      s/\s*,\s*/ /g;
      s/-\s+//g;
      print ECRITURE $_;
    }
    La variable $/ contient le séparateur d'enregistrement, par défaut le retour chariot. Appelée ainsi toute seule, il n'y a plus de séparateur d'enregistrement. Le "local" combiné au bloc "do" sert à limiter la portée de cette modification. J'ignore si c'est indispensable dans ton cas.
    Note que quelques optimisations sont peut-être possibles dans les regex (fusionner les deux premières, par exemple). Se pose aussi le problème (dans le cas général, pas dans le cas de la lettre - apocryphe - de George à Alfred) du distingo à faire entre le trait d'union et le tiret de césure, quand le premier fait office du second, mais là ça devient très complexe.

  4. #4
    Membre Expert
    Avatar de Woufeil
    Profil pro
    Étudiant
    Inscrit en
    Février 2006
    Messages
    1 076
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2006
    Messages : 1 076
    Par défaut
    Mouarf, j'avais mal lu, j'ai cru que la regex te sortait un ++... Là je comprenais vraiment plus

    L'explication de Schmorgluck est très bonne

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Février 2008
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 20
    Par défaut
    Ouais pardon j'ai mis ++ pour montrer le double espace car sinon on le voit pas bien.

    Sinon merci, en effet ça marche bien. Et oui, je suis bête, (\s+)? c'est équivalent à \s* .

    Merci bien pour votre aide.

  6. #6
    Expert confirmé
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    Avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2003
    Messages : 6 245
    Par défaut
    Citation Envoyé par Schmorgluck Voir le message
    La variable $/ contient le séparateur d'enregistrement, par défaut le retour chariot. Appelée ainsi toute seule, il n'y a plus de séparateur d'enregistrement. Le "local" combiné au bloc "do" sert à limiter la portée de cette modification. J'ignore si c'est indispensable dans ton cas.
    Il est toujours préférable de localiser les modifications des variables globales. Par contre le "do" est ici inutile : il sert normalement à transformer un bloc en expression (autrement dit en quelque chose qui renvoie une valeur), un simple bloc suffira.

    --
    Jedaï

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

Discussions similaires

  1. Remplacer caractère ' ( quote ) par "\n"
    Par Eric45 dans le forum C++
    Réponses: 3
    Dernier message: 28/11/2007, 00h56

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