Script concaténation deux fichier

Résolu
steph70 -  
 steph70190 -
Bonjour,

Je viens vers vous pour vous demander un coup de main sur un script que je dois réaliser sur un serveur unix en ksh.

J'ai deux fichiers que je dois concatener en ligne en un seul.

Le premier fichier est crée comme ceci :
mag;code_art;campagne;st_juillet;st_aout;etc


Le deuxième fichier est crée comme ceci :
code_art;campagne;pma_juillet;pma_aout;etc


et le fichier final doit etre comme cela :
mag;code_art;campagne;st_juillet;st_aout;etc;pma_juillet;pma_aout;etc...


Si vous pouviez m'aider ce serait extra parceque la je suis paumé depuis la première ligne

Merci d'avance à tous

Steph70
Configuration: Windows XP
Safari 530.5

37 réponses

  • 1
  • 2
Résumé de la discussion

La discussion porte sur la concaténation en ligne de deux fichiers CSV sous Unix en ksh, afin d'obtenir un fichier final regroupant les colonnes des deux sources. Plusieurs propositions visent à étendre join et à trier les données par code_art et campagne, avec des ajustements de formatage (séparateurs et colonnes vides) et l'utilisation de sed, awk ou perl. Des essais alternent entre for en ksh, création de fichiers temporaires par campagne et tentatives de jointure multiple, certaines évoquant des volumes proches de 400 000 lignes, donc sensibles à la performance. Des arguments émergent pour éviter join sur de grands ensembles et privilégier une fusion via awk ou Perl, ou des scripts dédiés, afin d'obtenir les colonnes manquantes sans réorganisation lourde.

Généré automatiquement par IA
sur la base des meilleures réponses
  1. kilian Messages postés 8675 Date d'inscription   Statut Modérateur Dernière intervention   1 526
     
    Donc il faut que tu jartes les doublons en même temps c'est ça?

    Je connais pas ksh, mais à ce que je vois, l'emploi du for semble être comme dans bash.
    Ca devrait ressembler à un truc du genre:

    all=""
    
    for $fichier in "fichier1 fichier2"
        for $token in "sed 's/;/ /' $fichier"
        do
            found=false
            for $elm in $all
            do
                if $elm == $token
                then
                    found = true
                fi
            done
            if $found == false
            then
                all="$all $token"
                echo $token >> fichier_union
            fi
        done
    done

    Ou quelque chose dans ce goût là.
    0
  2. steph70
     
    Bonjour Killian et merci pour ta réponse.

    je ne saisis pas totalement le script (désolé je suis un peu débutant) et celui me dit qu'il y a une erreur au for en ligne 4.

    Par hasard, après un FOR, il n'y a pas un "do" ?

    Et je ne saisis pas la variable tolken.

    Merci encore pour ton aide.

    Amicalement
    Steph70
    0
  3. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Salut,

    Pourquoi pas
    cat fic1 fic2 > fic3 && perl -pi -e 's/\n/;/' fic3
    --
    106485010510997108
    0
  4. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Re,

    Ou utiliser un tr "\n$" ";"
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    Salut,

    Il y a combien de champs sur chaque ligne ?

    Parce qu'il existe la commande "join" :
    ssh$ cat fich fic
    mag;code_art;campagne;st_juillet;st_aout;etc
    code_art;campagne;pma_juillet;pma_aout;etc
    
    ssh$ join -t';' -1 2 -2 1 -o '1.1,1.2,1.3,1.4,1.5,1.6,2.3,2.4,2.5'  fich fic
    mag;code_art;campagne;st_juillet;st_aout;etc;pma_juillet;pma_aout;etc
    
    ssh$
    ;-))
    0
  7. steph70
     
    Merci a tous,

    Le souci est que les deux fichiers ne peuvent pas simplement être joint, il faut que les lignes du premier correspondent bien aux lignes du deuxième.

    Ce que je veux dire c'est que dans le premier fichier, la première ligne ne correspond pas forcément à la première ligne du deuxième.

    De plus, a priori, il me semble que join n'affichera pas les lignes vides d'un des deux fichiers. Exemple, j'ai bien du st_juillet mais en face je n'ai pas de pma_juillet.

    Merci quand même pour votre aide précieuse, vous êtes tous super.

    Amicalement
    Steph70
    0
  8. steph70
     
    Bonjour,

    J'ai essayé join mais ca coince et j'ai un message d'erreur
    unexpected operator
    


    A l'aide

    Amicalement
    Steph70
    0
    1. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
       
      Merci d'afficher les fichiers, la commande et le message d'erreur (copier/coller du terminal).
      0
  9. steph70
     
    Pardon, est allé un peu vite.

    voici le script en complet .

    while [ `cat D_STO2.CSV` -ne EOF ];do
    join -t';' -1 2 -2 1 -o '1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,1.10,1.11,1.12,1.13,1.14,1.15,2.3,2.4,2.5,2.6,2.7,2.8,2.9,2.10,2.11,2.12,2.13,2.14' D_STO2.CSV D_PMA2.CSV >>stockpma.csv
    done
    


    Merci pour votre aide
    Steph70
    0
  10. steph70
     
    Pardon,

    le script ne comprend que la ligne "join", le reste est inutile.

    Par contre, j'ai un deuxième champs (campagne) qui devrait être utilisé pour le tri et à priori ca n'est pas possible avec join.

    J'ai bien pensé a faire des fichiers temporaires par campagne mais c'est extremement long. (y a un peu plus de 400 000lignes.

    Si vous avez une idée.

    Merci
    Amicalement
    Steph70
    0
  11. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    Sans des exemples des fichiers d'entrée c'est difficile de comprendre pourquoi la commande "join" merdoie ;-(
    0
  12. steph70
     
    Si tu veux voici un exemple.

    Le premier fichier comprend ceci :
    mag;code_art;campagne;st_juillet;st_aout;etc
    201;106;2007;12;23;etc
    201;206;2008;11;13;etc
    113;206;2007;12;14;etc
    112;208;2008;34;25;etc


    Le deuxième fichier comprend cela :
    code_art;campagne;pma_juillet;pma_aout;etc
    206;2007;112;118,etc
    201;2008;115;120;etc
    206;2008;175;195;etc
    106;2007;340;152;etc
    208;2008;32;12;etc
    etc.........</cotde>
    
    et le fichier final devrait ressembler à cela : 
    <code>mag;code_art;campagne;st_juillet;st_aout;etc;pma_juillet;pma­_aout;etc
    201;206;2008;11;13;etc;112;118;etc
    201;106;2007;12;23;etc;340;152;etc
    112;208;2008;34;25;etc;32;12;etc


    Amicalement
    Steph70
    0
  13. steph70
     
    Ce qui fait que je devrais faire 2 jointures : une sur le code_art et l'autre sur la campagne.

    Merci encore pour votre aide précieuse

    Amicalement
    steph70
    0
  14. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    Ça ne pourra malheureusement pas marcher avec join ;-((

    Extrait du man :
           fichier_1 et fichier_2 doivent être préalablement triés en ordre crois-
           sant (pas nécessairement numérique) sur  leur  champ  utilisé  pour  la
           fusion.
    Désolé ;-(
    0
  15. steph70
     
    Pas d'idée ? Sniff !!!!

    Amicalement
    Steph70
    0
  16. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 659
     
    hello
    comment arrives-tu à ces lignes avec les deux fichiers ?
    201;206;2008;11;13;etc;112;118;etc
    201;106;2007;12;23;etc;340;152;etc
    112;208;2008;34;25;etc;32;12;etc
    0
  17. steph70
     
    Bonjour,

    Ben justement c'est la question. Comment faire pour arriver à ce resultat.

    Amicalement
    Steph70
    0
  18. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 659
     
    je te demande quelle est la logique, méthode,intention,algorithme pour arriver à ça
    201;206;2008;11;13;etc;112;118;etc
    201;106;2007;12;23;etc;340;152;etc
    112;208;2008;34;25;etc;32;12;etc

    avec
    201;106;2007;12;23;etc
    201;206;2008;11;13;etc
    113;206;2007;12;14;etc
    112;208;2008;34;25;etc
    et
    206;2007;112;118,etc
    201;2008;115;120;etc
    206;2008;175;195;etc
    106;2007;340;152;etc
    208;2008;32;12;etc
    0
  19. steph70
     
    Ah ok, désolé, je suis un peu lent à la comprenote

    Et bien on compare les deux champs communs des fichiers que sont code_art et campagne, si les deux champs sont identiques on les inscrits en ligne dans un troisième fichiers en prenant soin malgré tout de ne pas inscrire ne double les champs de fusion (code_art et campagne)

    Après quelques recherches, il me semble que cela doit être possible avec awk et FR et NFR

    Mais malgré les exemples trouvés de ci dela sur le net, je n'arrive pas à mettre en forme.

    Y a t'il u pro de awk par ici ?

    Merci encore pour votre aide

    Amicalement
    Steph70
    0
  20. asevere Messages postés 13095 Date d'inscription   Statut Webmaster Dernière intervention   426
     
    Olà,

    Awk ne me parait pas le plus judicieux, il n'est pas fait pour lire & ttraiter deux fichiers simultanément :)

    Perso, j'utiliserait join, comme jp.

    Etant donné que join ne sait pas faire de jointure sur plus d'un champ, il faut commencer par deux petites transformations pour n'avoir qu'un seul champ!
    #!/bin/bash
    cat > fic1 << EOF
    mag;code_art;campagne;st_juillet;st_aout;etc
    201;106;2007;12;23;etc
    201;206;2008;11;13;etc
    113;206;2007;12;14;etc
    112;208;2008;34;25;etc
    EOF
    
    
    cat > fic2 << EOF
    code_art;campagne;pma_juillet;pma_aout;etc
    206;2007;112;118,etc
    201;2008;115;120;etc
    206;2008;175;195;etc
    106;2007;340;152;etc
    208;2008;32;12;etc
    EOF
    
    # 1: Transformer code_art;campagne en code_art@camapagne, et trier le fichier numeriquement sur le champ 2
    sed -r 's/^([^;]+);([^;]+);([^;]+);(.*)$/\1;\2@\3;\4/' fic1 |sort -n -t ';' -k 2 > fic1.mod
    
    # 1: Transformer code_art;campagne en code_art@camapagne, et trier le fichier numeriquement sur le champ 1
    sed -r 's/^([^;]+);([^;]+);(.*)$/\1@\2;\3/' fic2 |sort -n -t ';' -k 1 > fic2.mod
    
    #3: Joindre les fichiers sur les champ 2 du fichier 1 et 1 du fichier2, remettre le champ mag à la bonne place, et separer le champ code_art@campagne en deux champ distincts
    join -1 2 -2 1 -t ';' fic1.mod fic2.mod | sed -r 's/^(.+)@([^;]+);([^;]+);(.*)$/\3;\1;\2;\4/'


    A prioris, ça semble faire l'affaire sur les exemple donnés :)

    a plus

    PS: j'ai utiliser l'arobase en me basant sur l'idée qu'il ne devrait apparaitre à aucun autre endroit dans les fichiers, c'est fesable avec l'underscore, mais moins générique, ou avec tout autre caractère nonprésent :)
    0
  21. asevere Messages postés 13095 Date d'inscription   Statut Webmaster Dernière intervention   426
     
    PS2:

    J'avais pas vu que les fichiers étaient très volumineux... mais sans fichiers temporaires ça ne me parait difficilement jouable...

    Elle viennent d'ou ces données ? Si lle viennent d'une base de donnée, il faudrait extraire directement le fichier voulu (c'est une opération bien plus simple en sql, qu'en shell, d'ailleurs c'est a ça que ça sert)...
    0
    1. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
       
      Salut,

      J'ai la nette impression que tu t'es cassé les nénettes pour pas grand chose ;-((

      Si on en croit sa dernière explication la correspondance des champs ne se fait pas sur la même ligne des 2 fichiers joins côte à côte, mais sur la correspondance des champs de n'importe quelle ligne (enfin d'après les explications) ;-((

      Résultat escompté :
      201;206;2008;11;13;etc;112;118;etc
      201;106;2007;12;23;etc;340;152;etc
      112;208;2008;34;25;etc;32;12;etc 
      Résultat d'un paste :
      $ paste  fich1 fich2
      
      201;106;2007;12;23;etc  206;2007;112;118,etc
      201;206;2008;11;13;etc  201;2008;115;120;etc
      113;206;2007;12;14;etc  206;2008;175;195;etc
      112;208;2008;34;25;etc  106;2007;340;152;etc
              208;2008;32;12;etc
      
      ;-((((

      0
      1. asevere Messages postés 13095 Date d'inscription   Statut Webmaster Dernière intervention   426 > jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention  
         
        Ben pour moi, c'est une erreur dans la sortie exemple :) il a bien dit que ça devait être join sur code_art & campagne, en quel cas, la première ligne de l'exemple donné est fausse, puissque s'il s'agit bien du même article, les campagne ne sont pas les mêmes :)

        0
  • 1
  • 2