Kuinka muotoilla tulos oikein Awk printf -komennolla?

Minulla on seuraava tiedosto:

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| 

Yritän muotoilla tätä tiedostoa käyttämällä awk printf: tä seuraavaan haluttuun muotoon:

  1. säilytä sama kenttien järjestys (vasen -> oikea)
  2. pilkku ”,” FS
  3. vain kolmelle l ast-kentälle (5, 6, 7 dollaria) , joiden kaikkien numeroiden on oltava 4-numeroisia, jos vähemmän on etunolla ja vain 2 numeroa pisteen jälkeen, kuten 0123.12 tai 1234.10

Kirjoitin seuraavan awk-komennon

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

alla olevassa tuotoksessa on kuitenkin seuraavat ongelmat:

  1. ei ole kunnossa (vasen -> oikea)

  2. ei ole nollaa etupuolella

    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 

Voisiko joku ilmoittaa minulle, mikä on virheeni ja kuinka korjaan sen?

Kommentit

  • FYI, pilkkujen erottamiseen ilmoittamatta kutakin pilkua voit käyttää 'BEGIN {OFS=","}' tai vain

– mutta se ei ' t vastaa laajempaan kysymykseesi.

Vastaa

Sinulla on kentät oikeassa järjestyksessä, mutta ensimmäinen tulostuslauseke lisää uuden rivin (Output Record Separator), joten tietosi ovat siellä, mutta vain kääritty odottamatta.

Toinen asia on, että sanot printf: n käyttävän leveyttä 4; joka sisältää desimaalipilkun ja sen jälkeen olevat kaksi numeroa, jättäen vain yhden etunumerolle ja ei yhtään mitään täyttöä varten. Yritä käyttää 5: tä leveydellä, jotta tietosi täytetään neljään kokonaislukuun. Jos haluat 4 numeroa ennen desimaalipistettä, vaihda sen sijaan leveys 7: een.

Tämä on lyhin muutos, jonka tein ohjelmastasi sellaiseksi, joka tuottaa mielestäni sinun want:

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

Yhdistin useita { } -lohkoja yhdeksi ja yhdistäin myös tulosteet yhdeksi.

Jos kirjoitin awk-lauseesi tyhjästä, voisin tehdä jotain tällaista:

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 

Se asettaa nimenomaisesti syötekentän erotimen , Output Field Separator muuntaa nimenomaisesti kukin kentät itsestään ja tulostaa sitten halutut kentät OFS: n erottamalla ne.

Kommentit

  • Vau !!! Tämä on hienoa ja opin paljon. Arvostat todella aikaa ja informatiivista kuvausta 🙂 Paras!

Vastaa

Yksi tapa tehdä se:

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

Kommentit

  • @ Sato Katsura, Tnx paljon, se toimii täydellisesti. Saanen pyytää sinua selittämään skripteille ymmärtääksesi sen! Olen uusi Awkissa. Tarvitaan vain selitys ur-komentosarjan tälle osalle: {NF–; (i = NF-2; i < = NF; i ++) $ i = sprintf ("% 07.2f ", $ i)} 1 '

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *