Aquí tiene, uno
pase
solución paso a awk -
awk 'NR==FNR{a = a + $2;next} {c = ($2/a)*100;print $1,$2,c }' file file
[jaypal:~/Temp] cat file
1 10
2 10
3 20
4 40
[jaypal:~/Temp] awk 'NR==FNR{a = a + $2;next} {c = ($2/a)*100;print $1,$2,c }' file file
1 10 12.5
2 10 12.5
3 20 25
4 40 50
Actualización: Si pestaña es un necesario en la producción a continuación, sólo establece la variable OFS a "\ t".
[jaypal:~/Temp] awk -v OFS="\t" 'NR==FNR{a = a + $2;next} {c = ($2/a)*100;print $1,$2,c }' file file
1 10 12.5
2 10 12.5
3 20 25
4 40 50
del desbloqueo de patrón {acción} declaraciones:
El primer patrón es NR==FNR
. FNR es la variable incorporada de awk que realiza un seguimiento del número de registros (por defecto separados por una nueva línea) en un archivo dado. Entonces FNR en nuestro caso sería 4. NR es similar a FNR pero no se reinicia a 0. Continúa creciendo. Entonces NR en nuestro caso sería 8.
Este patrón será cierto solo para los primeros 4 registros y eso es exactamente lo que queremos. Después de leer detenidamente los 4 registros, asignamos el total a una variable a
. Tenga en cuenta que no lo inicializamos. En awk
no es necesario. Sin embargo, esto se rompería si toda la columna 2 es 0. Entonces puede manejarlo colocando una declaración if en la segunda declaración de acción, es decir, haga la división solo si a> 0 else di división por 0 o algo así.
next
es necesario porque realmente no queremos que se ejecute la instrucción second pattern {action}. next
le dice a awk que pare más acciones y pase al siguiente registro.
Una vez que se han analizado los cuatro registros, comienza el siguiente patrón {acción}, que es bastante directo. Hacer el porcentaje e imprimir la columna 1 y 2 junto con el porcentaje al lado de ellos.
Nota:Como @lhf se menciona en el comentario, esta sola línea sólo funcionará siempre y cuando usted tiene el conjunto de datos en un archivo. No funcionará si pasa datos a través de una tubería.
En los comentarios, hay una discusión pasando maneras de hacer esta entrada awk one-liner
toma de una pipe
en lugar de un file
. Bueno, la única forma en que podía pensar era almacenar los valores de columna en array
y luego usar for loop
para escupir cada valor junto con su porcentaje.
Ahora arrays
en awk
son associative
y nunca están en orden, es decir tirando de los valores fuera de las matrices no estarán en el mismo orden en que entraron. Así que si eso es aceptable, entonces el siguiente de una sola línea debería funcionar.
[jaypal:~/Temp] cat file
1 10
2 10
3 20
4 40
[jaypal:~/Temp] cat file | awk '{b[$1]=$2;sum=sum+$2} END{for (i in b) print i,b[i],(b[i]/sum)*100}'
2 10 12.5
3 20 25
4 40 50
1 10 12.5
Para conseguir el fin, se puede canalizar el resultado de sort
.
[jaypal:~/Temp] cat file | awk '{b[$1]=$2;sum=sum+$2} END{for (i in b) print i,b[i],(b[i]/sum)*100}' | sort -n
1 10 12.5
2 10 12.5
3 20 25
4 40 50
Esto es todo. ¡Gracias! – Martin
No hay problema. :) Pondré algunas explicaciones para referencia. –
Agradable, pero en realidad no es de una sola pasada. En particular, no se puede usar como filtro, es decir, leyendo de stdin. – lhf