Come formattare correttamente loutput con il comando Awk printf?

Ho il seguente file:

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| 

Sto cercando di formattare questo file utilizzando awk printf per avere il seguente formato desiderato:

  1. mantenere lo stesso ordine dei campi (sinistra -> destra)
  2. avere virgola “,” FS
  3. solo per l tre campi ($ 5, $ 6, $ 7) con tutti i numeri di 4 cifre, se less ha uno zero iniziale e solo 2 cifre dopo il punto come 0123.12 o 1234.10

ho scritto il seguente comando awk

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

tuttavia loutput di seguito presenta i seguenti problemi:

  1. non è in ordine (sinistra -> destra)

  2. non hanno lo zero iniziale

    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 

Qualcuno può farmi sapere qual è il mio errore e come risolverlo?

Commenti

  • Cordiali saluti, per la separazione delle virgole senza citare ogni virgola puoi usare 'BEGIN {OFS=","}' o semplicemente

—ma questo ' non risponde alla tua domanda più ampia.

Rispondi

I campi sono nellordine corretto, ma la tua prima istruzione print aggiunge una nuova riga (Separatore record di output), quindi i tuoi dati sono lì, ma sono semplicemente racchiusi in modo imprevisto.

Il secondo problema è che stai dicendo a printf di usare una larghezza di 4; che include il punto decimale e le due cifre dopo di esso, lasciandone solo uno per la cifra iniziale e nessuno per il riempimento. Prova a utilizzare 5 come larghezza, in modo che i tuoi dati vengano riempiti fino a quattro numeri totali. Se vuoi 4 cifre prima del punto decimale, cambia invece la larghezza in 7.

Questa è la modifica più breve che ho fatto dal tuo programma a qualcosa che emetta ciò che penso tu want:

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

Ho combinato più blocchi { } in uno e ho anche combinato le istruzioni print in uno solo.

Se dovessi scrivere la tua istruzione awk da zero, potrei fare qualcosa del genere:

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 

Imposta esplicitamente il separatore di campo di input , il separatore del campo di output, converte esplicitamente ciascuno dei campi da solo, quindi stampa i campi desiderati, separandoli con OFS.

Commenti

  • Wow !!! È fantastico e imparo molto. Apprezzo molto il tuo tempo e la descrizione informativa 🙂 Meglio!

Rispondi

Un modo per farlo:

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

Commenti

  • @ Sato Katsura, Tnx funziona perfettamente. Posso chiederti di spiegare ai tuoi script per capirlo! Sono nuovo in Awk. Serve solo la spiegazione per questa parte del tuo script: {NF–; per (i = NF-2; i < = NF; i ++) $ i = sprintf ("% 07.2f ", $ i)} 1 '

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *