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:
- garder le même ordre des champs (gauche -> droite)
- avoir une virgule « , » FS
- 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:
-
nest pas dans lordre (gauche -> droite)
-
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
– 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 '
'BEGIN {OFS=","}'
ou simplement