¿Cómo formatear correctamente la salida con el comando Awk printf?

Tengo el siguiente archivo:

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| 

Estoy intentando formatear este archivo usando awk printf para tener el siguiente formato deseado:

  1. mantener el mismo orden de campos (izquierda -> derecha)
  2. tener coma «,» FS
  3. solo para l ast tres campos ($ 5, $ 6, $ 7) con todos los números de 4 dígitos, si menos tiene un cero a la izquierda y solo 2 dígitos después del punto como 0123.12 o 1234.10

Escribí el siguiente comando awk

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

sin embargo, el resultado a continuación tiene los siguientes problemas:

  1. no está en orden (izquierda -> derecha)

  2. no tienen el cero a la izquierda

    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 

¿Alguien puede decirme cuál es mi error y cómo solucionarlo?

Comentarios

  • Para su información, para la separación por comas sin citar cada coma, puede usar 'BEGIN {OFS=","}' o simplemente

—pero eso no ' no responde a su pregunta más amplia.

Respuesta

Tiene los campos en el orden correcto, pero su primera declaración de impresión agrega una nueva línea (Separador de registros de salida), por lo que sus datos están allí, pero simplemente se envuelven inesperadamente.

El segundo problema es que le está diciendo a printf que use un ancho de 4; que incluye el punto decimal y los dos dígitos posteriores, dejando solo uno para el dígito inicial y ninguno para el relleno. Intente usar 5 como ancho, de modo que sus datos se rellenen hasta cuatro números en total. Si quieres 4 dígitos antes del punto decimal, cambia el ancho a 7.

Este es el cambio más corto que hice de tu programa a algo que da como resultado lo que creo que quiero:

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

Combiné varios bloques { } en uno, y también combiné las declaraciones de impresión en una sola.

Si tuviera que escribir su declaración awk desde cero, podría hacer algo como esto:

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 

Establece explícitamente el Separador de campo de entrada , el Separador de campos de salida, convierte explícitamente cada uno de los campos por sí solo, luego imprime los campos deseados, con el OFS separándolos.

Comentarios

  • ¡¡¡Vaya !!! Esto es genial y aprendo mucho. Realmente aprecio su tiempo y descripción informativa 🙂 ¡Mejor!

Respuesta

Una forma de hacerlo:

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

Comentarios

  • @ Sato Katsura, Tnx mucho funciona perfectamente. ¿Puedo pedirle que le explique los scripts para entenderlo? Soy nuevo en Awk. Solo necesito la explicación para esta parte de nuestro script: {NF–; para (i = NF-2; i < = NF; i ++) $ i = sprintf ("% 07.2f ", $ i)} 1 '

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *