Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 27/07/2016, à 00:04

Swiss_Knight

☑ [awk] Action différente sur la 1ère ligne et lister tout les champs?

Salut,
j'ai deux questions :

1. comment faire en sorte qu'awk exécute une commande différente sur la première ligne (header d'un fichier csv) et ensuite une autre commande pour toutes les autres lignes ?
Ceci me change toutes les lignes avec "des choses" , en fait il n'exécute que la première action si je comprends bien:

awk -F ";" 'NR=1 {print "des choses" }; NR>1 { print "des trucs"}' foo 

Merci 1.


2. Avec une liste de colonnes qui commence à s'allonger, ça devient "lourd" à saisir.... :

awk -F ";" 'NR=1 {print "CODE;"$3";"$4";"$5";"$6";"$7";"$8}' foo

Y a-t-il un moyen une fois qu'on sait qu'on va devoir print les éléments "3->dernier" tels quels, de ne pas les appeler les uns après les autres ?

Merci 2.

smile

Dernière modification par Swiss_Knight (Le 30/07/2016, à 12:01)


xuniL

Hors ligne

#2 Le 27/07/2016, à 00:08

Swiss_Knight

Re : ☑ [awk] Action différente sur la 1ère ligne et lister tout les champs?

Pas bouger, j'ai déjà trouvé la solution au point 1; il faut écrire un double signe égal puisqu'on fait une comparaison (je suis bête parfois... c'est affligeant):

awk -F ";" 'NR==1 {print "des choses" }; NR>1 { print "des trucs"}' foo 

xuniL

Hors ligne

#3 Le 27/07/2016, à 00:22

Swiss_Knight

Re : ☑ [awk] Action différente sur la 1ère ligne et lister tout les champs?

Bon pis je viens direct avec une question plus corsée, je ne sais pas si c'est réalisable ça :

Je montre le début du fichier :

$ head -n4 foo 
X;Y;OID;ID;OQTE;QTE;OTYPE;TYPE;Z
6073.344;10857.928;930;982963;0;XTX;49;comment;191.299
6073.591;10858.700;930;982963;0;XTX;49;comment;191.341
6073.831;10859.475;930;982963;0;XTX;49;comment;191.393

J'ai besoin de ça en sortie :

CODE;OID;ID;OQTE;QTE;OTYPE;TYPE
"FLW (6073.344 10857.928 191.299, 10858.700;930 191.341, 10859.475;930 191.393)";982963;0;XTX;49;comment

Où j'ai "FLW(X1 Y1 Z1, X2 Y2 Z2, X3 Y3 Z3)";suivi des autres valeurs. Ici j'ai trois enregistrements du fichier foo qui sont regroupés (faut voir les chiffres après X Y Z comme des indices) mais il peut y en avoir davantage.

Dans la colonne ID (ou OID c'est égal) j'ai un identifiant de groupe.

Il y a plusieurs enregistrement dans un groupe (chacun une ligne sur le fichier foo).
Je dois les regrouper dans une seule et même ligne, par groupe, en sortie. Comme dans l'exemple, mais là il n'y a qu'un groupe, d'OID=930 (ou d'ID=982963) ; chacun des trois enregistrements montrés ici ont donc le même ID car ils appartiennent au même groupe.
Le nombre d'enregistrements par groupe varie tout le temps. Il ne faut se baser que sur l'identifiant pour les regrouper dans une seule ligne en sortie. J'espère être clair. smile

Conceptuellement il faudrait faire un "if $3 de l'enregistrement N+1 est égal à $3 de l'enregistrement N précédent, alors on rajoute ses valeurs X Y Z dans la parenthèse".

Dernière modification par Swiss_Knight (Le 27/07/2016, à 00:28)


xuniL

Hors ligne

#4 Le 27/07/2016, à 06:30

pingouinux

Re : ☑ [awk] Action différente sur la 1ère ligne et lister tout les champs?

Bonjour,
Réponse à la question 2 du #1 :

awk -F\; 'NR>1{printf("CODE;");for(i=3;i<=NF;++i)printf("%s;",$i);printf("\n")}' foo

Pour ce qui est du #3, je n'ai rien compris…

Hors ligne

#5 Le 30/07/2016, à 12:00

Swiss_Knight

Re : ☑ [awk] Action différente sur la 1ère ligne et lister tout les champs?

En fait je décortique la réponse trouvée ailleurs ici pour clore le post convenablement :

awk -F";" '
NR==1 
    {print "CODE;"$3 FS $4 FS $5 FS $6 FS $7 FS $8}; 
NR>1 
    {a[$3]= $4 FS $5 FS $6 FS $7 FS $8; 
    b[$3]=(b[$3]?b[$3]", ":"")$1" "$2" "$NF;}
END
    {for(i in a) printf "\"FLW (%s)\";%s;%s\n", b[i], i, a[i]}' foo

Si je commence à bien comprendre les choses, la première opération dit ceci : séparateur = ; ensuite pour la 1ère ligne du fichier, on print CODE; le champ3; le champ4; ... ->;le champ8
Ensuite, pour les lignes 2 et suivantes (donc jusqu'à la fin) on met dans une sorte de variable a contenant un tableau [$3] toutes les variables : $4 ; $5 ; $6 ; $7 ; $8 de chaque enregistrement (i.e. chaque ligne).

On fait ensuite pareil après avoir ouvert une parenthèse, dans un tableau b[$3] où b[$3]?b[$3]" <-- ça je n'ai pas compris mais on dirait un test sur le nouveau tableau (??) qui doit permettre de stocker tous les champs qui suivent le test dans un seul enregistrement (i.e. une seule ligne de ce tableau) toutes celles dont le champ3 correspond à celui de l'enregistrement courant (ça doit aussi quelque part éviter les doublons des lignes suivantes je pense), suivi de "deux-points" et d'une parenthèse fermante puis les variables de champ $1 $2 et le dernier, $NF séparées ici par des espaces et non le séparateur de base qui ici est le point virgule. On range tout ça dans un tableau qu'on affecte à une variable b.

Finalement, pour chaque ligne du tableau de la variable a on print le code: "\FLW( suivi de toutes les lignes du tableau b " ; les lignes du tableau a et là j'ai pas compris non plus pourquoi il y avait besoin des deux :

i, a[i]

(??)

Enfin voilà, ça fonctionne plutôt très bien. smile


xuniL

Hors ligne