[GAWK] insérer 2 colonnes dans un tableau à un endroit précis

insérer 2 colonnes dans un tableau à un endroit précis [GAWK] - Shell/Batch - Programmation

Marsh Posté le 29-08-2006 à 17:21:08    

Hello,
 
Voici mon petit problème:
j'ai un tableau 1 de valeurs à 5 colonnes, je souhaite y remplacer les  colonnes 4 et 5 venant d'un autre tableau (tableau 2)  qui a lui aussi 5 colonnes. Je veux prendre les colonnes 4 et 5 de ce tableau 2 pour les mettre dans le tableau 1 en position 4e et 5e colonnes.
 
Je fais comme manip en gawk:
gawk '{print $1,$2,$3}' tableau1> nouveau_fichier
 
puis:
gawk '{print $4,$5}' tableau2 > nouveau_fichier  
le problème ici est que gawk efface tout, aussi est ce que c'est possible de préciser la position du print des colonnes dans le nouveau_fichier?
 
merci d'avance,
 :jap:  

Reply

Marsh Posté le 29-08-2006 à 17:21:08   

Reply

Marsh Posté le 29-08-2006 à 19:41:55    

Je vais commencer par répondre à tes deux questions:
 
Pour pouvoir utiliser plusieurs fichiers d'entrée avec AWK il faut utiliser la fonction getline.
Pour pouvoir formater une output (justification, nombre de décimales, ...) il faut utiliser printf.
 
Je te conseille de lire le man pour ces deux fonctions qui sont relativement complexes (surtout la syntaxe de printf).
 
Pour ton exemple, si j'ai bien compris tu as deux fichiers :
 
Le premier composé de 3 fields:

olivier@MiniPC:~/temp$ cat file1
a b c
f g h
k l m
p q r

 
Et le deuxième de 2 fields:

olivier@MiniPC:~/temp$ cat file2
d e
i j
n o
s t


Et le résultat devrait ressembler à:

olivier@MiniPC:~/temp$ cat file3
 a  b  c  d  e
 f  g  h  i  j
 k  l  m  n  o
 p  q  r  s  t


Voici le petit "programme" AWK permettant d'arriver à ce résultat en utisant getline pour lire file2 et un printf basique pour la mise en page:

olivier@MiniPC:~/temp$ cat test.awk
BEGIN {
        i=1 ; j=1
        while ((getline < "file2" ) > 0 ) {
                arr[i,4]=$1 ; arr[i,5]=$2
                i++
                }
        close (file2)
        }
{
        arr[j,1]=$1 ; arr[j,2]=$2 ; arr[j,3]=$3
        j++
}
END {
        for ( k=1 ; k <= i ; k++ ) {
                printf "%2s %2s %2s %2s %2s\n",arr[k,1],arr[k,2],arr[k,3],arr[k,4],arr[k,5]
                }
        }


Et la commande pour créer file3:

olivier@MiniPC:~/temp$ awk -f test.awk file1 > file3


 
Pour résumer rapidement, dans le "bloc" BEGIN, grâce à la commande getline, file2 est lu séquentiellement et les fields 4 et 5 d'un tableau arr[] sont populés en utilisant l'incrément i comme clé unique.
Dans le corps du "programme", le fichier file1 est lu séquentiellement et les fields 1,2,3 du tableau arr[] sont populés avec les données de file1.
Et dans le bloc END, les valeurs du tableau arr[] qui contient les données de file1 et file2 sont affichées en utilisant printf.
 
C'est assez basique, aucun contrôle n'est fait, et si le nombre de lignes est différent entre file1 et file2 la sortie sera décallée. Mais avec qques tests ça devrait passer ;)
 
Il y a certainement plus simple ... mais bon ...
 


---------------
Institutions européennes: Ensemble d'outils dont le but est de transformer une grande quantité d'argent en merde. Cette merde est utilisée pour créer de nouveaux fonctionnaires. L'argent restant payant des externes pour faire leur travail.
Reply

Marsh Posté le 31-08-2006 à 04:43:38    

Ses 2 fichiers en entrée ont déjà 5 colonnes, il veut 1, 2 et 3 de A et 4 et 5 de B. Suffit de modifier les indices dans tes scripts :) ou bien - si Gawk n'est pas à utiliser obligatoirement -  
utiliser cut suivi soit de paste soit de nl + join (numéroter pour envoyer à join qui apparemment demande un champ en commun pour agir, d'où le nl -m'enfin je connais pas trop ces commandes :) )

Message cité 1 fois
Message édité par phosphoreloaded le 31-08-2006 à 04:46:59
Reply

Marsh Posté le 31-08-2006 à 07:44:47    

phosphoreloaded a écrit :

Ses 2 fichiers en entrée ont déjà 5 colonnes, il veut 1, 2 et 3 de A et 4 et 5 de B.

:cry: ... 15 ans après la fin de mes études je lis toujours les énoncés en diagonale et réponds à côté ;)
 
Sinon il suffit de remplacer - arr[i,4]=$1 ; arr[i,5]=$2 - par - arr[i,4]=$4 ; arr[i,5]=$5 - dans le BEGIN pour répondre cette fois au problème ...


---------------
Institutions européennes: Ensemble d'outils dont le but est de transformer une grande quantité d'argent en merde. Cette merde est utilisée pour créer de nouveaux fonctionnaires. L'argent restant payant des externes pour faire leur travail.
Reply

Marsh Posté le 31-08-2006 à 11:47:16    

Voici une autre methode pour effectuer le travail demandé sans passer par un tableau (c'est uniquement pour monter une autre technique, je n'ai rien contre l'utilisation des tableaux) :

$ cat repcols.awk
# !/usr/bin/awk -f
BEGIN {
  if (ARGC != 3) {
      print "Arguments: File1 File2" > /dev/stderr;
      exit 1;
  }
  File1 = ARGV[1];
  File2 = ARGV[2];
  while (1) {
     if (getline < File2) {
       Field4 = $4;
       Field5 = $5;
       if (getline < File1) {
          $4 = Field4;
          $5 = Field5;
          print $0;
       } else {
          print "Fichier incomplet : " File1 > /dev/stderr;
          exit 2;
       }
     } else {
        if (getline < File1) {
          print "Fichier incomplet : " File2 > /dev/stderr;
          exit 3;
        } else
          exit 0;
     }
  }
}


Pour créer le nouveau fichier :

$ awk -f repcols.awk tableau1 tableau2 > nouveau_fichier


Si l'on met le fichier repcols.awk exécutable (chmod +x repcols.awk), on peut faire (attention, le vérifier le chemin pour awk en ligne 1 du script) :

$ repcols.awk tableau1 tableau2 > nouveau_fichier


Si ta version de awk ne gére pas /dev/stderr, il est possible d'écrire sur stderr par la methode :

print "Fichier incomplet : " File1 | "cat 1>&2";


 
Jean-Pierre.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed