Hur formateras utdata korrekt med kommandot Awk printf?

Jag har följande 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| 

Jag försöker formatera den här filen använder awk printf för att ha följande önskade format:

  1. behålla samma ordningsfält (vänster -> höger)
  2. har komma ”,” FS
  3. endast för l som tre fält ($ 5, $ 6, $ 7) med alla siffror som ska vara 4 siffror, om mindre har en ledande noll och bara två siffror efter punkten som 0123.12 eller 1234.10

Jag skrev följande awk-kommando

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

men nedanstående utdata har följande problem:

  1. är inte i ordning (vänster -> höger)

  2. har inte den ledande nollan

    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 någon snälla meddela mig vad som är mitt misstag och hur man fixar det?

Kommentarer

  • FYI, för kommaseparation utan att citera varje komma kan du använda 'BEGIN {OFS=","}' eller bara

– men det svarar inte ' t din bredare fråga.

Svar

Du har fälten i rätt ordning, men ditt första utskriftsuttalande lägger till en ny linje (Output Record Separator), så dina data finns där, men bara inslagna oväntat.

Det andra problemet är att du säger till printf att använda bredden 4; det inkluderar decimaltecknet och de två siffrorna efter det, och lämnar bara en för den ledande siffran och ingen för någon stoppning. Försök att använda 5 som bredden så att dina data fylls upp till fyra totalt antal. Om du vill ha fyra siffror före decimalpunkten, ändra sedan bredden till 7 istället.

Det här är den kortaste ändringen som jag gjorde från ditt program till något som visar vad jag tror vill ha:

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

Jag kombinerade flera { } block till en, och kombinerade också utskriftsuttalanden till ett.

Om jag skulle skriva ditt awk-uttalande från grunden kan jag göra något liknande:

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 ställer uttryckligen in inmatningsfältavgränsaren , Output Field Separator, konverterar uttryckligen vart och ett av fälten på egen hand och skriver sedan ut de önskade fälten, med OFS som separerar dem.

Kommentarer

  • Wow !!! Det här är fantastiskt och jag lär mig mycket. Uppskattar verkligen din tid och informativa beskrivning 🙂 Bäst!

Svar

Ett sätt att göra det:

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

Kommentarer

  • @ Sato Katsura, Tnx mycket det fungerar perfekt. Får jag be er snälla förklara för era skript för att förstå det! Jag är ny i Awk. Behöver bara förklaringen för den här delen av skriptet: {NF–; för (i = NF-2; i < = NF; i ++) $ i = sprintf ("% 07.2f ", $ i)} 1 '

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *