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
    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
    ;-))
    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
      
      1. Modérateur
        Merci ;-))
      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
      3. Modérateur
        @vanhellEssaye comme ça :
        perl -ne 's/\n/ / if /SELECT/../^FROM/;s/^FROM /\nFROM /;print'
        ;-))
      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;
      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
        ;-))
    2. 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...
      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]$
        ;-))
        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 ;-\
          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
            1. Modérateur
              Essaye comme ça :
              sed '
              /motcle1/ {
              :z
              N
              /motcle2$/ !b z
              s/\n[^\(mocle2\)]/ /g
              }
              '
              1. 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
                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...
                  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.
                2. [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]$
                  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 ?
                    1. Comme ça plus d'erreurs mais uniquement les 2 premières lignes affichées :

                      texte texte texte texte texte
                      texte texte texte
                      1. Modérateur
                        Essaie comme ça alors :
                        sed '
                        /motcle1/ {
                        :z
                        N
                        /motcle2$/ !b z
                        s/\n/ /g
                        s/motcle2/\n&/
                        }
                        '
                        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?
                          1. Modérateur
                            Salut,
                            sed '/motcle1/{:z;N;/motcle2$/!bz;s/\n/ /g;s/motcle2/\n&/}'
                            ;-))