Hvordan formateres output korrekt med Awk printf-kommando?

Jeg har følgende fil:

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| 

Jeg prøver at formatere denne fil ved hjælp af awk printf har følgende ønskede format:

  1. beholder den samme rækkefølge af felter (venstre -> højre)
  2. har komma “,” FS
  3. kun for l som tre felter ($ 5, $ 6, $ 7) med alle tallene til at være 4 cifre, hvis mindre har et førende nul og kun 2 cifre efter punktet som 0123.12 eller 1234.10

skrev jeg følgende awk-kommando

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

dog har nedenstående output følgende problemer:

  1. er ikke i orden (venstre -> højre)

  2. har ikke det førende nul

    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 

Kan nogen fortælle mig, hvad der er min fejl, og hvordan man løser det?

Kommentarer

  • FYI, til kommaadskillelse uden at citere hvert komma, kan du bruge 'BEGIN {OFS=","}' eller bare

—men det svarer ikke ' t til dit bredere spørgsmål.

Svar

Du har felterne i den rigtige rækkefølge, men din første udskrivningserklæring tilføjer en ny linje (Output Record Separator), så dine data er der, men bare pakket ind uventet.

Det andet spørgsmål er, at du fortæller printf at bruge en bredde på 4; der inkluderer decimaltegnet og de to cifre efter det, hvilket kun efterlader et for det forreste ciffer og ingen for nogen polstring. Prøv at bruge 5 som bredden, så dine data polstres op til fire samlede tal. Hvis du vil have 4 cifre før decimaltegnet, skal du ændre bredden til 7 i stedet.

Dette er den korteste ændring, jeg har foretaget fra dit program til noget, der sender det, jeg synes du ønsker:

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

Jeg kombinerede flere { } blokke til en og kombinerede også udskriftsudsagnene til en.

Hvis jeg skulle skrive din awk-sætning fra bunden, kan jeg muligvis gøre noget som dette:

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 

Det indstiller eksplicit inputfeltadskilleren , Output Field Separator, konverterer eksplicit hvert af felterne alene og udskriver derefter de ønskede felter, hvor OFS adskiller dem.

Kommentarer

  • Wow !!! Dette er fantastisk, og jeg lærer meget. Værdsat virkelig din tid og informative beskrivelse 🙂 Bedst!

Svar

En måde at gøre det på:

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

Kommentarer

  • @ Sato Katsura, Tnx meget, det fungerer perfekt. Må jeg bede dig forklare for dine scripts for at forstå det! Jeg er ny i Awk. Brug kun forklaringen på denne del af ur-scriptet: {NF–; for (i = NF-2; i < = NF; i ++) $ i = sprintf ("% 07.2f ", $ i)} 1 '

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *