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 :

substitution plusieurs lignes


Sujet :

Langage Perl

  1. #1
    Candidat au Club
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 4
    Points
    4
    Par défaut substitution plusieurs lignes
    Bonjour
    Voila maintenant plusieurs heures que je bataille avec un truc tout bete.

    Je souhaite substituer un texte sur plusieurs lignes avec sed.

    J'ai par exemple dans un fichier texte :
    toto
    titi
    tata

    Je voudrais tranformer
    toto
    titi

    en

    tata

    Je fais donc la commande :
    $chaine =~ s/toto\ntiti/tata/g;

    Mais ca ne fonctionne pas et je ne vois pas pourquoi car je représente bien le saut de ligne par \n

    MERCI POUR VOTRE AIDE

  2. #2
    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
    Points : 12 256
    Points
    12 256
    Billets dans le blog
    1
    Par défaut
    Quelle technique utilises-tu pour lire le fichier texte? Peux-tu montrer ton code qui ne marche pas?

  3. #3
    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
    En effet, si tu lis ton fichier "ligne à ligne", tu n'aurais jamais un caractère \n entre deux textes, tu auras, au pire, un \n à la fin d'une chaine.
    Si tu veux regrouper plusieurs lignes ensembles, soit :
    - tu lis ligne à ligne et ne réalise ton traitement (filtrage et écriture du résultat) qu'en présence de deux lignes lues... ce qui peut ne pas être simple
    - tu lis le fichier "en entier" sous forme d'une chaine unique (slurp the file : $/ = undef; $file = <$FILE>; )

    Pour la première option, un exemple :

    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
    open my $F, "<", $file or die "Cant open file $file for reading : $!";
    my $previous_line;
    while (defined(my $line = <$F>)) {
      my $two_lines = join "", grep defined, ($previous_line, $line);
      #say "2lines=[$two_lines]";
      if ($two_lines =~ s/titi\ntoto/tata/s) {
        $line = $two_lines;
      }
      elsif (defined $previous_line) {
        print $previous_line;
      }
      $previous_line = $line;
     
      if (eof $F) {
        print $line;
      }
    }
    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

  4. #4
    Candidat au Club
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Bonjour et merci pour le retour. Voici ce que je fais :

    Je lis mon fichier et le mets dans une chaine : chaine qui sera la base de mon travail.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    my $myfile = "/tmp/myfile.cfg";
    open my($file), '<', $confCEEBD or die "Couldn't open $myfile : $!\n";
    while( my $line = <$file> ) {
    	chomp($line) ;
    	$chaine .= $line ."\n";
    }
    close ($file);
    Dans mon fichier, j'ai les lignes
    toto
    titi

    Je voudrais transformer les 2 lignes qui sont maintenant dans ma chaine :

    Transformer :
    toto
    titi

    en

    tata


    Je fais donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $chaine =~ s/toto\ntiti/tata/g;
    print $chaine;
    En faisant un print chaine je vois que la substitution n'a pas eu lieu :-(

    Merci pour ton aide !

  5. #5
    Candidat au Club
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par Philou67430 Voir le message
    En effet, si tu lis ton fichier "ligne à ligne", tu n'aurais jamais un caractère \n entre deux textes, tu auras, au pire, un \n à la fin d'une chaine.
    Si tu veux regrouper plusieurs lignes ensembles, soit :
    - tu lis ligne à ligne et ne réalise ton traitement (filtrage et écriture du résultat) qu'en présence de deux lignes lues... ce qui peut ne pas être simple
    - tu lis le fichier "en entier" sous forme d'une chaine unique (slurp the file : $/ = undef; $file = <$FILE>; )

    Pour la première option, un exemple :

    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
    open my $F, "<", $file or die "Cant open file $file for reading : $!";
    my $previous_line;
    while (defined(my $line = <$F>)) {
      my $two_lines = join "", grep defined, ($previous_line, $line);
      #say "2lines=[$two_lines]";
      if ($two_lines =~ s/titi\ntoto/tata/s) {
        $line = $two_lines;
      }
      elsif (defined $previous_line) {
        print $previous_line;
      }
      $previous_line = $line;
     
      if (eof $F) {
        print $line;
      }
    }
    Merci pour ta réponse philou67430 et effectivement "Plus j'apprends, et plus je mesure mon ignorance" car ton code me fait tourner la tête
    Mais en effet, je ne lis pas le fichier ligne par ligne. Je crée une chaine de caractère avec mon fichier et je travaille ensuite sur cette chaîne.

  6. #6
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2013
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 247
    Points : 406
    Points
    406
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while( my $line = <$file> ) {
    	chomp($line) ;
    	$chaine .= $line ."\n";
    }
    Si tu construis ta chaine de caractère alors mets un séparateur peut être moins compliqué à catcher que "\n" genre # et ainsi tu cherches titi#toto

  7. #7
    Candidat au Club
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par 6ril23 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while( my $line = <$file> ) {
    	chomp($line) ;
    	$chaine .= $line ."\n";
    }
    Si tu construis ta chaine de caractère alors mets un séparateur peut être moins compliqué à catcher que "\n" genre # et ainsi tu cherches titi#toto
    Le problème, c'est que je travaille sur des fichiers de configuration qui ont plein de caractères spéciaux dont le # et qui ne sont pas les mêmes à chaque fois. :-(

  8. #8
    Candidat au Club
    Inscrit en
    Février 2008
    Messages
    7
    Détails du profil
    Informations forums :
    Inscription : Février 2008
    Messages : 7
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par devets Voir le message
    Le problème, c'est que je travaille sur des fichiers de configuration qui ont plein de caractères spéciaux dont le # et qui ne sont pas les mêmes à chaque fois. :-(
    Bon et bien tout fonctionne dans mon code en fait. Le seul hic c'est que j'avais des ^M :-( de m.....

    Merci a tous pour vos orientations !

  9. #9
    Membre averti
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2013
    Messages
    247
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2013
    Messages : 247
    Points : 406
    Points
    406
    Par défaut
    les ^M sont généralement car tes retours à la lignes sont de la forme \r\n: ton fichier est peut être issu de Windows ou de certains UNIX

  10. #10
    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 devets Voir le message
    Bonjour et merci pour le retour. Voici ce que je fais :

    Je lis mon fichier et le mets dans une chaine : chaine qui sera la base de mon travail.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    while( my $line = <$file> ) {
    	chomp($line) ;
    	$chaine .= $line ."\n";
    }
    close ($file);
    Cette partie de code se résume à ce que je t'avais indiqué précédemment :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $/ = undef; $chaine = <$file>;


    Pour la suite, il faut connaitre l'origine du fichier (DOS/windows ou Unix) afin de connaitre le séparateur de ligne (\n ou \r\n) pour écrire la bonne regexp.
    Dans le doute, tu peux essayer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $chaine =~ s/toto[\n\r]+titi/tata/g;
    print $chaine;
    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

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

Discussions similaires

  1. Substitution sur plusieurs lignes de suite
    Par princebenin dans le forum Langage
    Réponses: 10
    Dernier message: 22/01/2008, 08h19
  2. Réponses: 2
    Dernier message: 10/05/2004, 07h55
  3. TDBGrid - Un enregistrement sur plusieurs lignes
    Par BRODU dans le forum Bases de données
    Réponses: 2
    Dernier message: 09/05/2004, 07h53
  4. Réponses: 14
    Dernier message: 09/04/2004, 13h44
  5. Define sur plusieurs lignes
    Par Gogoye dans le forum C
    Réponses: 6
    Dernier message: 06/10/2003, 11h45

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