Ogni riga contiene testo e numeri in una colonna. Devo calcolare la somma dei numeri in ogni riga. Come posso fare ciò? Grazie
esempio.log contiene:
time=31sec
time=192sec
time=18sec
time=543sec
La risposta dovrebbe essere 784
Ogni riga contiene testo e numeri in una colonna. Devo calcolare la somma dei numeri in ogni riga. Come posso fare ciò? Grazie
esempio.log contiene:
time=31sec
time=192sec
time=18sec
time=543sec
La risposta dovrebbe essere 784
Risposte:
Con una versione più recente (4.x) di GNU awk
:
awk 'BEGIN {FPAT="[0-9]+"}{s+=$1}END{print s}'
Con altri awk
s prova:
awk -F '[a-z=]*' '{s+=$2}END{print s}'
s+0
nel caso in cui s
sia vuoto, verrà stampato 0
anziché vuoto.
s
può essere vuoto; se i dati di input non contengono righe (ovvero se non sono presenti input ). In quel caso ci sono due comportamenti possibili; 1) nessun input => nessun output, o 2) emette sempre qualcosa, se solo 0. Entrambi sono opzioni sensibili a seconda del contesto dell'applicazione. L' +0
opzione di indirizzamento 2). Per affrontare l'opzione 1) preferiresti scrivere END {if(s) print s}
. - Pertanto non ha senso assumere entrambe le opzioni (per questo caso d'angolo senza dati) fino a quando non viene specificato dalla domanda.
awk -F= '{sum+=$2};END{print sum}'
time=1.4e5sec
Un altro GNU awk
:
awk -v RS='[0-9]+' '{n+=RT};END{print n}'
Uno perl
:
perl -lne'$n+=$_ for/\d+/g}{print$n'
Uno 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'='
invece di--field-separator =
man awk
unico dà -F fs
e--field-separator fs
-F'='
oppure -F '='
sono 2 i modi di fare -F fs
(fs è "=" nel tuo caso). Ho aggiunto le virgolette singole per garantire che fs sia correttamente visto e interpretato da awk, non dalla shell (utile se la fs è ';' per esempio)
Tutti hanno pubblicato un post fantastico awk
risposte , che mi piacciono molto.
Una variante di @cuonglm che sostituisce grep
con sed
:
sed 's/[^0-9]//g' example.log | paste -sd'+' - | bc
sed
strisce tutto tranne i numeri.paste -sd+ -
comando unisce tutte le linee come un'unica lineabc
valuta l'espressioneDovresti usare una calcolatrice.
{ tr = \ | xargs printf '[%s=]P%d+p' | dc; } <infile 2>/dev/null
Con le tue quattro righe che stampano:
time=31
time=223
time=241
time=784
E più semplicemente:
tr times=c ' + p' <infile |dc
... che stampa ...
31
223
241
784
Se la velocità è ciò che stai cercando, allora dc
è ciò che desideri. Tradizionalmente era bc
il compilatore - e lo è ancora per molti sistemi.
dc
più vicino possibile. Di cosa stai parlando?
perl
il set di strumenti unix standard - non ha molto senso se si utilizzano strumenti GNU compilati su una toolchain GNU. Tutto il gonfiore che può influire negativamente sulle prestazioni di Perl è anche in tutti quei programmi di utilità GNU compilati da GNU. Triste ma vero. È necessario un set di strumenti reale, semplicemente costruito e semplice per giudicare con precisione la differenza. Come un set di cimeli di cimelio staticamente collegato, ad esempio, alle librerie di musl - in questo modo puoi mettere in panchina il paradigma di uno strumento / un lavoro rispetto a quello di uno strumento per dominarli tutti.
Attraverso python3,
import re
with open(file) as f:
m = f.read()
l = re.findall(r'\d+', m)
print(sum(map(int, l)))
re.findall
restituisce un elenco di stringhe, questo non funzionerà
sum(int(e) for e in l)
è più pitonico.
Soluzione 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.
Versione breve:
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