Cum să formatați corect ieșirea cu comanda Awk printf?

Am următorul fișier:

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| 

Încerc să formatez acest fișier folosind awk printf pentru a avea următorul format dorit:

  1. păstrați aceeași ordine de câmpuri (stânga -> dreapta)
  2. au virgulă „,” FS
  3. numai pentru l ast trei câmpuri (5 $, 6 $, 7 $) având toate numerele cu 4 cifre, dacă mai puțin au zero zero și doar 2 cifre după punctul ca 0123.12 sau 1234.10

Am scris următoarea comandă awk

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

totuși rezultatul de mai jos are următoarele probleme:

  1. nu este în ordine (stânga -> dreapta)

  2. nu au zero zero

    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 

Poate cineva să-mi spună care este greșeala mea și cum să o remediez?

Comentarii

  • FYI, pentru separarea virgulelor fără a cita fiecare virgulă, puteți utiliza 'BEGIN {OFS=","}' sau doar

—dar asta nu ' nu răspunde la întrebarea dvs. mai largă.

Răspundeți

Aveți câmpurile în ordinea corectă, dar prima declarație de tipărire adaugă o linie nouă (Separator de înregistrări de ieșire), astfel încât datele dvs. sunt acolo, dar sunt doar împachetate în mod neașteptat.

A doua problemă este că îi spuneți printf să folosească o lățime de 4; care include punctul zecimal și cele două cifre de după acesta, lăsând doar una pentru cifra de întâmpinare și niciuna pentru nicio umplutură. Încercați să utilizați 5 ca lățime, astfel încât datele dvs. să fie completate până la patru numere totale. Dacă doriți 4 cifre înainte punctul zecimal, atunci schimbați lățimea la 7 în schimb.

Aceasta este cea mai scurtă schimbare pe care am făcut-o de la programul dvs. la ceva care generează ceea ce cred want:

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

Am combinat mai multe blocuri { } într-unul și, de asemenea, am combinat instrucțiunile de tipărire într-unul singur.

Dacă ar fi să scriu declarația dvs. awk de la zero, aș putea face așa ceva:

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 

Setează în mod explicit separatorul de câmp de intrare , Separatorul de câmpuri de ieșire, convertește în mod explicit fiecare dintre câmpurile pe cont propriu, apoi tipărește câmpurile dorite, cu OFS le separă.

Comentarii

  • Uau !!! Este minunat și învăț multe. Apreciază cu adevărat timpul și descrierea informativă 🙂 Cel mai bun!

Răspuns

O modalitate de a face acest lucru:

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

Comentarii

  • @ Sato Katsura, Tnx mult funcționează perfect. Vă rog să vă rog să explicați scripturile pentru a o înțelege! Sunt nou în Awk. Ai nevoie doar de explicația pentru această parte a scriptului tău: {NF–; for (i = NF-2; i < = NF; i ++) $ i = sprintf ("% 07.2f ", $ i)} 1 '

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *