Concaténation en ksh

Bonsoir,

je me trouve face à un problème:

j'ai deux fichiers avec plusieurs lignes avec une seule chaîne de caractères commune aux deux.

cat fic1
25678;type1;harrys;6789;hji
67890;type4;uname;6799;kloo
67890;type3;basic;6089;lois

cat fic2
udhk;juikop;cassiop;768888
khkq;skdjh;99900;6789
qdsss;uuud;uname;uioo
67890;jjuii;sdds;00097

comment faire pour avoir un seul fichier dont se suivent les lignes qui ont les caractères communs?

exemple de sortie (new_file):
25678;type1;harrys;6789;hji
khkq;skdjh;99900;6789

67890;type4;uname;6799;kloo
qdsss;uuud;uname;uioo

67890;type3;basic;6089;lois
67890;jjuii;sdds;00097

je sèche... j'ai même pas la moindre petite idée...

merci pour votre aide

5 réponses

  1. Contributeur
    essayer cet algorithme, peut-être plus rapide, si il fonctionne bien !!
    $ awk -F ";" -v f=fic2 'BEGIN{nr=1; while(getline < f){for(n=1; n<=NF; n++)t[nr, $n]++; t2[nr++]=$0}} {for(l=1; l<nr; l++){split($0, a); for(m=1; m<=NF; m++)if(t[l, a[m]] && t2[l]){print $0 RS t2[l]; t2[l]=""; next}}}' fic1
    25678;type1;harrys;6789;hji
    khkq;skdjh;99900;6789
    67890;type4;uname;6799;kloo
    qdsss;uuud;uname;uioo
    67890;type3;basic;6089;lois
    67890;jjuii;sdds;00097
    $
    
    1. Contributeur
      essayer avec awk
      $ awk -F ";" 'FNR==NR {t[++l]=$0; next} {for(n=1; n<=l;n++){if(!t[n])continue; split(t[n], a); for(m=1; m<=NF; m++)if(a[m]==$m){print $0 RS t[n]; t[n]=""}} next}' fic2 fic1
      25678;type1;harrys;6789;hji
      khkq;skdjh;99900;6789
      67890;type4;uname;6799;kloo
      qdsss;uuud;uname;uioo
      67890;type4;uname;6799;kloo
      67890;jjuii;sdds;00097
      $ 
      
      1. Ah ben si il y a un maître de awk, je m'incline bien bas ;-)

        J'ai d'ailleurs dit l'autre fois que si on faisait une boucle dans un script c'est qu'on avait raté quelque chose...
      2. C'est à moi de m'incliner bien bas...! Chapeau. Je m'attendais effectivement à un awk mais celui là faut aller le chercher loin et chui nul...
        Des que j'ai mon Pc sous la main j'essaye. Tu peux expliquer grossièrement?

        1000 merci
      3. Re
        je viens d'essayer... malheureusement pour les très gros fichiers de plusieurs ko ça ne me rend jamais la main après 10 minutes. et quand je fais un top (HPUX) je m'aperçois que c'est extrêmement consommateur de cpu.
        il doit y a voir un truc qui va pas :(

        j'y retourne :)
      4. Contributeur
        effectivement, pour chaque ligne de fic1, il teste chaque champs de fic1 avec chaque champ de chaque ligne de fic2; si il y a un champ égal, on imprime les 2 lignes et on met la ligne de fic2 à 0 pour ne plus la tester.
        comment faire autrement ?
      5. Contributeur
        j'ai déplacé le dernier next pour sortir plus vite de la boucle quand un champ est trouvé
        awk -F ";" 'FNR==NR {t[++l]=$0; next} {for(n=1; n<=l;n++){if(!t[n])continue; split(t[n], a); for(m=1; m<=NF; m++)if(a[m]==$m){print $0 RS t[n]; t[n]=""; next}}}' fic2 fic1
    2. merci pour vos réponses:
      j'étais trop fatigué hier soir ... plus moyen de lire le moindre ls :/

      @dubcek
      le seul critère c'est que les lignes contenant au moins une chaîne de caractères en commun soit ensemble.
      dans ton exemple:
      cat fic1
      67890;type4;uname;6799;kloo
      67890;type3;basic;6089;lois

      cat fic2
      qdsss;uuud;uname;uioo
      67890;jjuii;sdds;00097

      => cat fic_final

      67890;jjuii;sdds;00097
      67890;type3;basic;6089;lois
      67890;type4;uname;6799;kloo
      qdsss;uuud;uname;uioo

      dans le mien normalement seul 2 champs sont identiques à chaque fois.

      @Flashy Joe:
      je n'ai pas bash d'installé, faudrait que je teste
      (je viens d'essayer en ash sur un synology et ça retourne rien... dommage parce que ça avait l'air pas mal... tu viens de me tendre un fil directeur ;) )

      Merci ;)
      1. ksh est compatible bash, il suffit de changer la première ligne en
        #!/bin/ksh

        Résultat :
        flachy@biduloscope:~$ apt-cache show ksh
        Package: ksh
        Version: 93u+20120801-1
        [...]
        flachy@biduloscope:~$ ./test.sh
        25678;type1;harrys;6789;hji
        khkq;skdjh;99900;6789
        
        67890;type4;uname;6799;kloo
        67890;jjuii;sdds;00097
        
        67890;type4;uname;6799;kloo
        qdsss;uuud;uname;uioo
        
        67890;type3;basic;6089;lois
        67890;jjuii;sdds;00097
        
        
      2. ksh n'est pas installé sur mon syno... je testerai de toutes façon au boulot lundi

        en tout merci pour ton aide ;)
    3. Contributeur
      hello
      quand plusieurs lignes ont un champ commun, quel est le critère ? l'ordre des lignes ?
      cat fic1
      67890;type4;uname;6799;kloo
      67890;type3;basic;6089;lois
      
      cat fic2
      qdsss;uuud;uname;uioo
      67890;jjuii;sdds;00097
      
      1. Salut,
        je sais pas si c'est le plus simple, mais ça fonctionne :
        #!/bin/bash
        
        t1="25678;type1;harrys;6789;hji
        67890;type4;uname;6799;kloo
        67890;type3;basic;6089;lois"
        
        f2="test.tmp"
        echo "udhk;juikop;cassiop;768888
        khkq;skdjh;99900;6789
        qdsss;uuud;uname;uioo
        67890;jjuii;sdds;00097" > $f2
        
        std_IFS=$IFS
        
        for l in $t1
        do
         IFS=";"
         for pattern in $l
         do
          res=$(egrep "\<${pattern}\>" $f2)
          if [ -n "$res" ]
          then
           echo "$l"
           echo "$res"
           echo 
          fi
          unset res
         done;
         IFS=$std_IFS
        done;
        
        rm $f2
        


        ;-) Flachy Joe ;-)