Aide commande ed/sed/awk/perl

Résolu
Bonjour,
J'aimerai dans un fichier texte, supprimer tous les retours à la ligne seulement pour le texte contenu entre motcle1 et motcle2 (la ligne de motcle1 incluse) et laisser le reste du texte inchangé.
motcle1 et motcle2 sont toujours en début de ligne.

Par exemple :

texte texte texte texte texte
texte texte texte
motcle1
texte texte
texte
texte texte texte
motcle2
texte texte
texte

doit devenir :

texte texte texte texte texte
texte texte texte
motcle1 texte texte texte texte texte texte
motcle2
texte texte
texte

Comment faire ça avec sed? (ou autre)
Merci d'avance pour votre aide!
Configuration: UNIX
KSH

15 réponses

Résumé de la discussion

Le problème consiste à supprimer les retours à la ligne entre motcle1 et motcle2 dans un fichier texte, la ligne motcle1 étant incluse et le reste du texte restant inchangé. Plusieurs solutions exploitent des scripts en perl, sed ou ed pour fusionner les lignes uniquement dans le bloc délimité, tout en préservant motcle1 et motcle2 et les délimitations. Par exemple, une approche Perl utilise une substitution sur la plage délimitée par motcle1 et motcle2 pour transformer les retours en espaces et réinsérer un saut après motcle2, mais des ajustements demeurent. D'autres solutions citent Sed ou Ed, permettant de grouper les lignes jusqu'à motcle2 et de remplacer les sauts par des espaces tout en évitant d'altérer les lignes après la délimitation.

Bobot (l’IA à votre service)
  1. Modérateur
    Salut,
    sed '/motcle1/{:z;N;/motcle2$/!bz;s/\n/ /g;s/motcle2/\n&/}'
    ;-))
    0
    1. Merci pour la réponse super rapide!
      Je viens d'essaye mais j'obtiens cette erreur :

      sed: The label /motcle1/{:z;N;/motcle2$/!bz;s/\n/ /g;s/motcle2/\n&/} is greater than eight characters.

      Je suis sur un environement UNIX AIX, j'ai la commande sed mais pas gsed, peut être a cause de ça non?
      0
      1. Modérateur
        Essaie comme ça alors :
        sed '
        /motcle1/ {
        :z
        N
        /motcle2$/ !b z
        s/\n/ /g
        s/motcle2/\n&/
        }
        '
        0
        1. Comme ça plus d'erreurs mais uniquement les 2 premières lignes affichées :

          texte texte texte texte texte
          texte texte texte
          0
          1. Modérateur
            Bizarre chez moi ça marche bien :
            [tmpfs]$ cat plop
            texte texte texte texte texte
            texte texte texte
            motcle1
            texte texte
            texte
            texte texte texte
            motcle2
            texte texte
            texte
            
            [tmpfs]$ sed '
            /motcle1/ {
            :z
            N
            /motcle2$/ !b z
            s/\n/ /g
            s/motcle2/\n&/
            }
            ' plop
            texte texte texte texte texte
            texte texte texte
            motcle1 texte texte texte texte texte texte
            motcle2
            texte texte
            texte
            
            [tmpfs]$  
            ;-\ ??

            Tu peux faire un copier/coller comme le mien de ce que tu as d'affiché dans ton terminal ?
            0
            1. [test]$ cat sed.txt
              texte texte texte texte texte
              texte texte texte
              motcle1
              texte texte
              texte
              texte texte texte
              motcle2
              texte texte
              texte
              [test]$ sed '
              > /motcle1/ {
              > :z
              > N
              > /motcle2$/ !b z
              > s/\n/ /g
              > s/motcle2/\n&/
              > }
              > ' sed.txt
              texte texte texte texte texte
              texte texte texte
              [test]$
              0
              1. Non en faite ça fonctionne presque, le fichier sur lequel je testé provenait de windows donc fin de ligne avec \r\n...

                Avec le même fichier crééer directement sur le serveur j'obtiens maintenant ça :

                texte texte texte texte texte
                texte texte texte
                motcle1 texte texte texte texte texte texte nmotcle2
                texte texte
                texte

                C'est preque bon il y a un juste un bug juste avant le "motcle2" il a un un "n" au lieu d'un retour a la ligne, je ne sais pas ou est passé l'antislah XD
                Bizare surtout que ça fonctionne chez toi...
                0
                1. Modérateur
                  Bizarre effectivement ;-\

                  Par contre chez moi c'est du GNU/Linux et pas du AIX...

                  Essaies de supprimer "s/motcle2/\n&/" et refais un test.
                  0
              2. J'obtiens ceci :
                $ sed '
                > /motcle1/ {
                > :z
                > N
                > /motcle2$/ !b z
                > s/\n/ /g
                > }
                > ' sed.txt
                texte texte texte texte texte
                texte texte texte
                motcle1 texte texte texte texte texte texte motcle2
                texte texte
                texte
                0
                1. Modérateur
                  Essaye comme ça :
                  sed '
                  /motcle1/ {
                  :z
                  N
                  /motcle2$/ !b z
                  s/\n[^\(mocle2\)]/ /g
                  }
                  '
                  0
                  1. Presque! de plus en plus pret lol

                    texte texte texte texte texte
                    texte texte texte
                    motcle1 exte texte exte exte texte texte
                    motcle2
                    texte texte
                    texte

                    le "t" en moins dans "mocle2" c'est fait expres?

                    Je pensais que c'était une faute de frappe mais en remmettant le t je n'ai plus aucun changement par rapport au fichier d'origine :

                    texte texte texte texte texte
                    texte texte texte
                    motcle1
                    texte texte
                    texte
                    texte texte texte
                    motcle2
                    texte texte
                    texte
                    0
                    1. Modérateur
                      Là je sèche :-((

                      Chez moi tout marche bien ;-\

                      Je parierai plus sur le fait que tu sois sur AIX, doit y avoir (je ne sais où) des interactions entre sed et le shell ;-\
                      0
                      1. Modérateur
                        Tu peux toujours essayer avec "ed" :
                        [tmpfs]$ cat plop
                        texte texte texte texte texte
                        texte texte texte
                        motcle1
                        texte texte
                        texte
                        texte texte texte
                        motcle2
                        texte texte
                        texte
                        
                        [tmpfs]$ ed -s plop <<<$'/motcle1/,/motcle2/g/$/s/.$/& /g\n/motcle1/,/motcle2/-1j\nw'
                        
                        [tmpfs]$ cat plop
                        texte texte texte texte texte
                        texte texte texte
                        motcle1 texte texte texte texte texte texte
                        motcle2
                        texte texte
                        texte
                        [tmpfs]$
                        ;-))
                        0
                        1. Rebonjour!
                          Non ça ne fonctionne pas sur cette machine avec ed, la shell est ksh ça vient surement de la.
                          Il faudrait trouver une solution avec awk ou perl...
                          0
                          1. Modérateur
                            Salut,
                            $ cat fichier.txt
                            texte texte texte texte texte
                            texte texte texte
                            motcle1
                            texte texte
                            texte
                            texte texte texte
                            motcle2
                            texte texte
                            texte
                            $ perl -ne 's/\n/ / if /motcle1/../motcle2/;s/motcle2 /\nmotcle2\n/;print' fichier.txt
                            texte texte texte texte texte
                            texte texte texte
                            motcle1 texte texte texte texte texte texte
                            motcle2
                            texte texte
                            texte
                            
                            0
                            1. Modérateur
                              Merci ;-))
                              0
                            2. Salut,
                              Merci ça fonctionne bien, même un peu trop lol j'explique :

                              $cat fictest
                              CONNECT TO ORACLE (&CONXORA);
                              CREATE TABLE ALIAS.TABLECREEE AS
                              SELECT ID_PERS,
                              ID_GRP_PERS, AGE_PERS
                              NB_ENF, MAX('GRP') AS MAXG
                              FROM TAB_PERS_GRP_PERS
                              WHERE DATE_DEB <= &DATE_FIN
                              AND (DATE_FIN IS NULL OR DATE_DEB > &DATE_FIN)
                              );
                              DISCONNECT FROM ORACLE;

                              perl -ne 's/\n/ / if /SELECT/../FROM/;s/FROM /\nFROM\n/;print' fictest

                              CONNECT TO ORACLE (&CONXORA);
                              CREATE TABLE ALIAS.TABLECREEE AS
                              SELECT ID_PERS, ID_GRP_PERS, AGE_PERS NB_ENF, MAX('GRP') AS MAXG
                              FROM
                              TAB_PERS_GRP_PERS WHERE DATE_DEB <= &DATE_FIN
                              AND (DATE_FIN IS NULL OR DATE_DEB > &DATE_FIN)
                              );
                              DISCONNECT
                              FROM
                              ORACLE;

                              Il faudrait que ça change juste entre SELECT et FROM donc ça c'est bon, mais la ça rajoute aussi un retour à la ligne après FROM et des retour à la ligne apres chaque mot de la dernière ligne (si ça peut aider pour ne pas prendre en compte "DISCONNECT FROM ORACLE" , les mots clés "SELECT" et "FROM" sont toujours en début de ligne.
                              Merci d'avance
                              0
                            3. Modérateur
                              @vanhellEssaye comme ça :
                              perl -ne 's/\n/ / if /SELECT/../^FROM/;s/^FROM /\nFROM /;print'
                              ;-))
                              0
                            4. @jipicyPresque!
                              Ca fonctionne mais ça enleve toujours le retour a la ligne avant le "WHERE"

                              J'obtient ça :

                              CONNECT TO ORACLE (&CONXORA);
                              CREATE TABLE ALIAS.TABLECREEE AS
                              SELECT ID_PERS, ID_GRP_PERS, AGE_PERS NB_ENF, MAX('GRP') AS MAXG
                              FROM TAB_PERS_GRP_PERS WHERE DATE_DEB <= &DATE_FIN
                              AND (DATE_FIN IS NULL OR DATE_DEB > &DATE_FIN)
                              );
                              DISCONNECT FROM ORACLE;

                              et il faudrait ça :

                              CONNECT TO ORACLE (&CONXORA);
                              CREATE TABLE ALIAS.TABLECREEE AS
                              SELECT ID_PERS, ID_GRP_PERS, AGE_PERS NB_ENF, MAX('GRP') AS MAXG
                              FROM TAB_PERS_GRP_PERS
                              WHERE DATE_DEB <= &DATE_FIN
                              AND (DATE_FIN IS NULL OR DATE_DEB > &DATE_FIN)
                              );
                              DISCONNECT FROM ORACLE;
                              0
                            5. Modérateur
                              @vanhellVa falloir attendre lami20j, n'étant pas un grand spécialiste de Perl pour ma part, désolé ;-(

                              Sinon, j'ai ça avec "ed" (essaie on sait jamais) :
                              echo 'H
                              /SELECT/,/^FROM/g/$/s/.$/& /g
                              /SELECT/,/^FROM/-1j
                              ,p' | ed -s fic
                              ;-))
                              0
                          2. Modérateur
                            Et comme ça :
                            [tmpfs]$ echo 'H
                            /motcle1/,/motcle2/g/$/s/.$/& /g
                            /motcle1/,/motcle2/-1j
                            .
                            w' | ed -s plop
                            ???

                            Édit : C'est plus simple comme ça...

                            Version affichage :
                            $ echo '/motcle1/,/motcle2/g/$/s/.$/& /g
                            /motcle1/,/motcle2/-1j
                            ,p' | ed -s plop
                            texte texte texte texte texte
                            texte texte texte
                            motcle1 texte texte texte texte texte texte
                            motcle2
                            texte texte
                            texte
                            Version écriture :
                            $ echo '/motcle1/,/motcle2/g/$/s/.$/& /g
                            /motcle1/,/motcle2/-1j
                            w' | ed -s plop
                            ;-))
                            0