Usando awk para sumar los valores de una columna, basados en los valores de otra columna

Estoy tratando de sumar ciertos números en una columna usando awk. Me gustaría sumar solo la columna 3 de los «herreros» para obtener un total de 212. Puedo sumar toda la columna usando awk pero no solo los «herreros». Tengo:

awk "BEGIN {FS = "|"} ; {sum+=$3} END {print sum}" filename.txt 

También estoy usando masilla. Gracias por la ayuda.

smiths|Login|2 olivert|Login|10 denniss|Payroll|100 smiths|Time|200 smiths|Logout|10 

Responder

awk -F "|" "$1 ~ /smiths/ {sum += $3} END {print sum}" inputfilename 
  • La bandera -F establece el separador de campo; Lo pongo entre comillas simples porque es un carácter especial de shell.
  • Luego, $1 ~ /smiths/ aplica el siguiente {bloque de código} solo a las líneas donde el primer campo coincide con la expresión regular /smiths/.
  • El resto es el mismo que su código.

Tenga en cuenta que, dado que en realidad no está usando una expresión regular aquí, solo un valor específico, podría fácilmente use:

awk -F "|" "$1 == "smiths" {sum += $3} END {print sum}" inputfilename 

Que verifica la igualdad de cadenas. Esto es equivalente a usar la expresión regular /^smiths$/, como se menciona en otro respuesta, que incluye el ^ delimitador para que solo coincida con el inicio de la cadena (el comienzo del campo 1) y el $ delimitador solo coincidir con el final de la cadena. No estoy seguro de qué tan familiarizado está con las expresiones regulares. Son muy poderosas, pero en este caso, podría usar una verificación de igualdad de cadenas con la misma facilidad.

Comentarios

  • Por cierto, mi referencia de awk favorita es grymoire.com/Unix/Awk.html . Página muy útil .
  • ¡Gracias @Wildcard! Pude agregar ordenadamente un tamaño sin comprimir de archivos particulares en un archivo zip grande según su consejo 🙂

Respuesta

Otro enfoque es usar matrices asociativas awk, más información aquí . Esta línea produce el resultado deseado:

awk -F "|" "{a[$1] += $3} END{print a["smiths"]}" filename.txt 

Como efecto secundario, la matriz almacena todos los demás valores:

awk -F "|" "{a[$1] += $3} END{for (i in a) print i, a[i]}" filename.txt 

Resultado:

smiths 212 denniss 100 olivert 10 

Comentarios

  • Esta es la respuesta correcta

Respuesta

Muy bien hasta ahora. Todo lo que necesita hacer es agregar un selector antes del bloque para agregar la suma. Aquí verificamos que el primer argumento contiene solo «smiths»:

awk "BEGIN {FS = "|"} ; $1 ~ /^smiths$/ {sum+=$3} END {print sum}" 

Puede acortarlo un poco especificando el separador de campo como una opción. En awk, generalmente es una buena idea inicializar las variables en la línea de comando:

awk -F"|" "$1 ~ /^smiths$/ {sum+=$3} END {print sum}" 

Respuesta

Personalmente, preferiría mantener la sección awk lo más simple posible y hacer todo lo que pueda sin ella . La lógica combinada no aprovecha el poder de las canalizaciones de Unix y, por lo tanto, es más difícil de entender, depurar o modificar para casos de uso estrechamente relacionados.

cat filename.txt | perl -pe "s{.*|}{}g" | awk "{sum+=$1} END {print sum}" 

Responde

cat filename.txt | grep smiths | awk -F "|" "{sum+=$NF} END {print sum}" 
  • -F opción para especificar el separador .
  • $NF es para «última columna».

Comentarios

  • cat y grep son innecesarios aquí.
  • ¿Por qué grep no es necesario @Andrey? OP quiere agregar solo " smiths " filas. Usted ' necesita modificar la declaración awk, ¿verdad?
  • @EL sí, la declaración awk debe modificarse a /smiths/{...} si la llamada grep no está ahí. Esta es una modificación trivial, pero proporciona importantes beneficios: disminuye el número de procesos en ejecución, simplifica el control de errores y hace que el código sea más claro.

Deja una respuesta

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