Jede Zeile enthält Text und Zahlen in einer Spalte. Ich muss die Summe der Zahlen in jeder Zeile berechnen. Wie kann ich das machen? Danke
example.log enthält:
time=31sec
time=192sec
time=18sec
time=543sec
Die Antwort sollte 784 sein
Jede Zeile enthält Text und Zahlen in einer Spalte. Ich muss die Summe der Zahlen in jeder Zeile berechnen. Wie kann ich das machen? Danke
example.log enthält:
time=31sec
time=192sec
time=18sec
time=543sec
Die Antwort sollte 784 sein
Antworten:
Mit einer neueren Version (4.x) von GNU awk:
awk 'BEGIN {FPAT="[0-9]+"}{s+=$1}END{print s}'
Mit anderen awks versuchen:
awk -F '[a-z=]*' '{s+=$2}END{print s}'
s+0für den Fall, dass sleer ist, wird es 0statt leer gedruckt .
sleer sein kann. Wenn die Eingabedaten keine Zeilen enthalten (dh wenn überhaupt keine Eingabe erfolgt ). In diesem Fall sind zwei Verhaltensweisen möglich. 1) keine Eingabe => keine Ausgabe oder 2) immer etwas ausgeben, wenn nur 0. Beide Optionen sind je nach Anwendungskontext sinnvoll. Die +0Adressierung Option 2). Um Option 1) anzusprechen, müssten Sie lieber schreiben END {if(s) print s}. - Daher ist es nicht sinnvoll, eine der beiden Optionen (für diesen Eckfall ohne Daten) anzunehmen, bis sie in der Frage angegeben sind.
awk -F= '{sum+=$2};END{print sum}'
time=1.4e5sec
Ein weiterer GNU awk:
awk -v RS='[0-9]+' '{n+=RT};END{print n}'
Eine perlEins:
perl -lne'$n+=$_ for/\d+/g}{print$n'
Ein POSIX eins:
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'='verwenden--field-separator =
man awkeinziger gibt -F fsund--field-separator fs
-F'='oder es -F '='gibt zwei Möglichkeiten, dies zu tun -F fs(in Ihrem Fall ist fs "="). Ich habe die einfachen Anführungszeichen hinzugefügt, um sicherzustellen, dass das fs von awk richtig gesehen und interpretiert wird, nicht von der Shell (nützlich, wenn das fs zum Beispiel ';' ist)
Jeder hat tolle awkAntworten gepostet , die ich sehr mag.
Eine Variation von @cuonglm ersetzt grepdurch sed:
sed 's/[^0-9]//g' example.log | paste -sd'+' - | bc
sedStreifen alles außer den Zahlen.paste -sd+ -Befehl verbindet alle Zeilen zu einer einzigen Zeilebcwertet den Ausdruck ausSie sollten einen Taschenrechner verwenden.
{ tr = \ | xargs printf '[%s=]P%d+p' | dc; } <infile 2>/dev/null
Mit Ihren vier Zeilen, die gedruckt werden:
time=31
time=223
time=241
time=784
Und einfacher:
tr times=c ' + p' <infile |dc
... was druckt ...
31
223
241
784
Wenn Geschwindigkeit das ist, wonach Sie streben, dcist es das, was Sie wollen. Traditionell war es bcder Compiler - und ist es immer noch für viele Systeme.
dcso nahe wie ich es beurteilen kann. Worüber redest du?
perldas Standard-Unix-Toolset als Benchmark verwenden - ist es nicht sehr sinnvoll, GNU-Tools zu verwenden, die in einer GNU-Toolchain kompiliert wurden. Alles, was die Leistung von Perl negativ beeinflussen kann, ist auch in all diesen GNU-kompilierten GNU-Utils enthalten. Traurig aber wahr. Sie benötigen ein echtes, einfach aufgebautes, einfaches Toolset, um den Unterschied genau beurteilen zu können. Wie ein Erbstück-Werkzeugkasten, der statisch mit den Bibliotheken der Muslime verknüpft ist - auf diese Weise können Sie das Ein-Werkzeug / Ein-Job-Paradigma mit dem Ein-Werkzeug-um-sie-alle-zu-regieren-vergleichen.
Durch python3,
import re
with open(file) as f:
m = f.read()
l = re.findall(r'\d+', m)
print(sum(map(int, l)))
re.findallgibt eine Liste von Zeichenketten zurück, dies wird nicht funktionieren
sum(int(e) for e in l)ist mehr pythonisch.
Reine Bash-Lösung (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.
Kurzfassung:
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