Cada línea contiene texto y números en una columna. Necesito calcular la suma de los números en cada fila. ¿Cómo puedo hacer eso? Gracias
example.log contiene:
time=31sec
time=192sec
time=18sec
time=543sec
La respuesta debería ser 784
Cada línea contiene texto y números en una columna. Necesito calcular la suma de los números en cada fila. ¿Cómo puedo hacer eso? Gracias
example.log contiene:
time=31sec
time=192sec
time=18sec
time=543sec
La respuesta debería ser 784
Respuestas:
Con una versión más nueva (4.x) de GNU awk
:
awk 'BEGIN {FPAT="[0-9]+"}{s+=$1}END{print s}'
Con otro awk
intento:
awk -F '[a-z=]*' '{s+=$2}END{print s}'
s+0
en caso de que s
esté vacío, se imprimirá en 0
lugar de estar vacío.
s
puede estar vacío; si los datos de entrada no contienen líneas (es decir, si no hay ninguna entrada ). En ese caso hay dos comportamientos posibles; 1) sin entrada => sin salida, o 2) siempre genera algo, si solo es 0. Ambas son opciones sensibles según el contexto de la aplicación. La +0
opción de direccionamiento 2). Para abordar la opción 1) preferiría escribir END {if(s) print s}
. - Por lo tanto, no tiene sentido asumir ninguna de las opciones (para este caso de esquina sin datos) hasta que la pregunta lo especifique.
awk -F= '{sum+=$2};END{print sum}'
time=1.4e5sec
Otro GNU awk
:
awk -v RS='[0-9]+' '{n+=RT};END{print n}'
A perl
uno:
perl -lne'$n+=$_ for/\d+/g}{print$n'
Un POSIX:
tr -cs 0-9 '[\n*]' | grep . | paste -sd + - | bc
sed 's/=/ /' file | awk '{ sum+=$2 } END { print sum}'
sed
:awk --field-separator = '{ sum+=$2 } END { print sum}' data.dat
-F'='
lugar de--field-separator =
man awk
únicos -F fs
--field-separator fs
-F'='
o -F '='
hay 2 formas de hacer el -F fs
(fs es "=" en su caso). Agregué las comillas simples para asegurar que fs sea visto e interpretado correctamente por awk, no el shell (útil si la fs es ';' por ejemplo)
Todos han publicado awk
respuestas increíbles , que me gustan mucho.
Una variación para reemplazar @cuonglm grep
con sed
:
sed 's/[^0-9]//g' example.log | paste -sd'+' - | bc
sed
tiras todo excepto los números.paste -sd+ -
comando une todas las líneas como una sola línea.bc
evalúa la expresiónDeberías usar una calculadora.
{ tr = \ | xargs printf '[%s=]P%d+p' | dc; } <infile 2>/dev/null
Con sus cuatro líneas que imprime:
time=31
time=223
time=241
time=784
Y más simplemente:
tr times=c ' + p' <infile |dc
... que imprime ...
31
223
241
784
Si lo que buscas es velocidad, entonces dc
es lo que quieres. Tradicionalmente era bc
su compilador, y todavía lo es para muchos sistemas.
dc
tan cerca como puedo ver. ¿De qué estás hablando?
perl
conjunto de herramientas estándar de Unix, realmente no tiene mucho sentido si utiliza herramientas GNU compiladas en una cadena de herramientas GNU. Toda la hinchazón que puede afectar negativamente el rendimiento de Perl también se encuentra en todas esas utilidades GNU compiladas por GNU. Triste pero cierto. Necesita un conjunto de herramientas real, simple y simple para juzgar con precisión la diferencia. Como, por ejemplo, un conjunto de herramientas de reliquias estáticamente vinculado a las librerías musl, de esa manera puede comparar el paradigma de una herramienta / un trabajo con el de una herramienta para gobernarlos a todos.
A través de python3,
import re
with open(file) as f:
m = f.read()
l = re.findall(r'\d+', m)
print(sum(map(int, l)))
re.findall
devuelve una lista de cadenas, esto no va a funcionar
sum(int(e) for e in l)
sea más pitónico.
Solución de bash pura (Bash 3+):
while IFS= read -r line; do # While it reads a line:
if [[ "$line" =~ [0-9]+ ]]; then # If the line contains numbers:
((counter+=BASH_REMATCH[0])) # Add the current number to counter
fi # End if.
done # End loop.
echo "Total number: $counter" # Print the number.
unset counter # Reset counter to 0.
Version corta:
while IFS= read -r l; do [[ "$l" =~ [0-9]+ ]] && ((c+=BASH_REMATCH)); done; echo $c; c=0
PS4='$((x+=${time%s*}))' time=0 x=0 sh -x <infile