Comment formater correctement la sortie avec la commande Awk printf?

Jai le fichier suivant:

echo filename dfT08r352|30.5|2010/06/01|2016/08/29|2281|6.24503764544832|74.9404517453799| zm00dr121|37|2008/03/05|2011/09/12|1285.95833333333|3.52076203513575|42.249144421629| ccvd00121|41.6|2008/03/05|2012/03/05|1461|4|48| sddf00121|39.6|2008/03/05|2012/09/10|1649.95833333333|4.51733972165184|54.208076659822| fttt00121|41|2008/03/05|2013/09/16|2020.95833333333|5.53308236367785|66.3969883641342| ghhyy0121|42.2|2008/03/05|2014/03/18|2203.95833333333|6.03410905772302|72.4093086926762| 

Jessaye de formater ce fichier en utilisant awk printf pour avoir le format souhaité suivant:

  1. garder le même ordre des champs (gauche -> droite)
  2. avoir une virgule « , » FS
  3. uniquement pour les l trois champs (5 $, 6 $, 7 $) ayant tous les nombres à 4 chiffres, si less a un zéro non significatif et seulement 2 chiffres après le point comme 0123.12 ou 1234.10

Jai écrit la commande awk suivante

awk -F"|" "{print $1","$2","$3","$4}{format = "%04.2f,%04.2f,%04.2f,"}{printf format, $5,$6,$7}" filename 

cependant, la sortie ci-dessous présente les problèmes suivants:

  1. nest pas dans lordre (gauche -> droite)

  2. nont pas de zéro non significatif

    dfT08r352,30.5,2010/06/01,2016/08/29 2281.00,6.25,74.94,zm00dr121,37,2008/03/05,2011/09/12 1285.96,3.52,42.25,ccvd00121,41.6,2008/03/05,2012/03/05 1461.00,4.00,48.00,sddf00121,39.6,2008/03/05,2012/09/10 1649.96,4.52,54.21,fttt00121,41,2008/03/05,2013/09/16 2020.96,5.53,66.40,ghhyy0121,42.2,2008/03/05,2014/03/18 

Quelquun peut-il sil vous plaît me faire savoir quelle est mon erreur et comment y remédier?

Commentaires

  • Pour info, pour la séparation par virgule sans guillemets chaque virgule, vous pouvez utiliser 'BEGIN {OFS=","}' ou simplement

– mais cela ' ne répond pas à votre question plus large.

Réponse

Vous avez les champs dans le bon ordre, mais votre première instruction dimpression ajoute une nouvelle ligne (Output Record Separator), donc vos données sont là, mais juste encapsulées de manière inattendue.

Le deuxième problème est que vous « dites à printf dutiliser une largeur de 4; qui inclut le point décimal et les deux chiffres après celui-ci, ne laissant quun seul pour le premier chiffre et aucun pour tout remplissage. Essayez dutiliser 5 comme largeur, afin que vos données soient complétées jusquà quatre nombres au total. Si vous voulez 4 chiffres avant le point décimal, changez la largeur en 7 à la place.

Cest le changement le plus court que jai fait de votre programme à quelque chose qui produit ce que je pense que vous want:

awk -F"|" "{ format = "%05.2f,%05.2f,%05.2f"; print $1","$2","$3","$4"," sprintf(format, $5,$6,$7)}" filename 

Jai combiné plusieurs blocs { } en un seul, et jai également combiné les instructions dimpression en un seul.

Si je devais écrire votre déclaration awk à partir de zéro, je pourrais faire quelque chose comme ceci:

awk -v FS=\| -v OFS=, "{ $5=sprintf("%05.2f", $5); $6=sprintf("%05.2f", $6); $7=sprintf("%05.2f", $7); print $1,$2,$3,$4,$5,$6,$7}" filename 

Il définit explicitement le séparateur de champ dentrée , le séparateur de champs de sortie, convertit explicitement chacun des champs individuellement, puis imprime les champs souhaités, avec lOFS les séparant.

Commentaires

  • Wow !!! Cest génial et japprends beaucoup. Nous apprécions vraiment votre temps et votre description informative 🙂 Meilleur!

Réponse

Une façon de le faire:

awk -F \| -v OFS=, "{ NF--; for(i = NF-2; i <= NF; i++) $i = sprintf("%07.2f", $i) } 1" filename 

Commentaires

  • @ Sato Katsura, Tnx beaucoup ça marche parfaitement. Puis-je vous demander sil vous plaît expliquer à vos scripts pour le comprendre! Je suis nouveau dans Awk. Seulement besoin de lexplication pour cette partie de votre script: {NF–; pour (i = NF-2; i < = NF; i ++) $ i = sprintf ("% 07.2f ", $ i)} 1 '

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *