Kürzeste Befehl, um die Summe einer Spalte der Ausgabe auf Unix zu berechnen?
Frage
Ich bin sicher, es ist eine schnelle und einfache Möglichkeit, die Summe einer Spalte von Werten auf Unix-Systemen (mit so etwas wie awk
oder xargs
vielleicht), aber dem Schreiben einen Shell-Skript zur Berechnung der Zeilen Zeile zu analysieren Zeile das ist einzige, was im Moment in den Sinn kommt.
Zum Beispiel, was ist der einfachste Weg, um den folgenden Befehl zu modifizieren, um die Summe für die SEGSZ Spalte zu berechnen und anzuzeigen (70300)?
ipcs -mb | head -6
IPC status from /dev/kmem as of Mon Nov 17 08:58:17 2008
T ID KEY MODE OWNER GROUP SEGSZ
Shared Memory:
m 0 0x411c322e --rw-rw-rw- root root 348
m 1 0x4e0c0002 --rw-rw-rw- root root 61760
m 2 0x412013f5 --rw-rw-rw- root root 8192
Lösung
ipcs -mb | tail +4 | awk '{ sum += $7 } END { print sum }'
oder ohne Schwanz:
ipcs -mb | awk 'NR > 3 { sum += $7 } END { print sum }'
Mit awk mit bc beliebig lange Ergebnisse (Kredite Jouni K.
) haben:
ipcs -mb | awk 'NR > 3 { print $7 }' | paste -sd+ | bc
Andere Tipps
Ich würde versuchen, eine Berechnung String zu erstellen und ihn an bc wie folgt:
- grep die Linien, die die Zahlen enthalten
- sed entfernt alle Zeichen vor (und nach) der Nummer auf jeder Zeile
- xargs das Ergebnis (eine Reihe von Zahlen durch Leerzeichen getrennt zu bekommen)
- tr anslate die Rohlinge auf '+' Zeichen
- guter Appetit bc
ipcs -mb | grep -w '^m ' | sed 's/^.*\s//' | xargs | tr ' ' + | bc
Sieht aus wie das etwas länger ist als die awk Lösung, aber für alle, die nicht lesen können (und verstehen), um die ungerade awk Code dies einfacher sein kann, erfassen ...: -)
Wenn bc ist nicht installiert Sie doppelte Klammern in Schritt 5 das Ergebnis berechnen verwenden können:
-
echo $(( $(ipcs -mb | grep -w '^m ' | sed 's/^.*\s//' | xargs | tr ' ' +) ))
oder -
SUM=$(( $(ipcs -mb | grep -w '^m ' | sed 's/^.*\s//' | xargs | tr ' ' +) ))
oder -
(( SUM=$(ipcs -mb | grep -w '^m ' | sed 's/^.*\s//' | xargs | tr ' ' +) ))
Der Abstand nach und vor den doppelten Klammern ist optional.
Ich habe ein Dienstprogramm-Skript, das einfach aufaddiert alle Spalten. Es ist in der Regel leicht genug, um die, die Sie von der einzeiligen Ausgabe wollen zu greifen. Als Bonus sind einige SI-Suffixe erkannt.
#!/usr/bin/awk -f
# Sum up numerical values by column (white-space separated)
#
# Usage: $0 [file ...]
#
# stern, 1999-2005
{
for(i = 1; i <= NF; ++i) {
scale = 1
if ($i ~ /[kK]$/) { scale = 1000 }
if ($i ~ /[mM]$/) { scale = 1000*1000 }
if ($i ~ /[gG]$/) { scale = 1000*1000*1000 }
col[i] += scale * $i;
}
if (NF > maxnf) maxnf = NF;
}
END {
for(i = 1; i <= maxnf; ++i) { printf " %.10g", col[i] }
print "";
}
Beispiel mit benutzerdefinierten Feldtrennzeichen:
$ head /etc/passwd | addcol -F:
0 0 45 39 0 0 0
Python-Lösung
#!/usr/bin/env python
text= file("the_file","r")
total= 0
for line in text:
data = line.split()
if data[0] in ('T', 'Shared', 'IPC'): continue
print line
segsize= int(data[6])
total += segsize
print total
Die meisten Linux-Distributionen haben Python.
Wenn Sie stdin als Teil eines pipline zu verarbeiten, verwenden Sie
import sys
total = 0
for line in sys.stdin:
...etc...
Wenn Sie davon ausgehen, dass es immer 3 Kopfzeilen:
import sys
total = 0
for line in sys.stdin.readlines()[3:]:
total += int(line.split()[6])
print total
Einzeiler:
import sys; print sum( [int(line.split()[6]) for line in sys.stdin.splitlines()[3:]] )
Ich weiß, diese Frage etwas veraltet ist, aber ich kann nicht „meine“ Antwort hier sehen, also entschied ich mich dennoch posten. Ich würde gehen mit einer Kombination aus
- Schwanz (um die Zeilen, die Sie benötigen)
- tr (schrumpfen mehrere consequitive Räume ein)
- Schnitt (um nur die benötigte Spalte)
- Paste (auf jede Zeile mit einem
+
Zeichen verketten) - bc (die tatsächliche Berechnung zu tun)
ipcs
keinen Ausgang auf meinem System nicht geben, so werde ich Demo es nur mit df
:
# df
Filesystem 1K-blocks Used Available Use% Mounted on
rootfs 33027952 4037420 27312812 13% /
udev 10240 0 10240 0% /dev
tmpfs 102108 108 102000 1% /run
/dev/xvda1 33027952 4037420 27312812 13% /
tmpfs 5120 0 5120 0% /run/lock
tmpfs 204200 0 204200 0% /run/shm
/dev/xvda1 33027952 4037420 27312812 13% /var/www/clients/client1/web1/log
/dev/xvda1 33027952 4037420 27312812 13% /var/www/clients/client1/web2/log
/dev/xvda1 33027952 4037420 27312812 13% /var/www/clients/client1/web3/log
/dev/xvda1 33027952 4037420 27312812 13% /var/www/clients/client1/web4/log
/dev/xvda1 33027952 4037420 27312812 13% /var/www/clients/client2/web5/log
/dev/xvda1 33027952 4037420 27312812 13% /var/www/clients/client2/web6/log
# df | tail -n +2 | tr -s ' ' | cut -d ' ' -f 2 | paste -s -d+ | bc
264545284
Ich weiß, dass diese besondere Berechnung auf meinem System tut nicht wirklich Sinn machen, aber es zeigt das Konzept.
Alle Stücke dieser Lösung wird in den anderen Antworten gezeigt, aber nie in dieser Kombination.
könnten Sie beginnen, indem die Daten durch cut
läuft - die zumindest die Spalten stutzen würde.
Sie sollten dann in der Lage sein, um Rohr, das in grep
, Stripping-out nicht-Numerik.
Dann ... na ja, dann bin ich nicht sicher. Es könnte möglich sein, Rohr, das bc
. Wenn nicht, ist es sicherlich zu einem Shell-Skript übergeben werden könnte jedes Element hinzuzufügen.
Wenn Sie verwendet tr
die Zeilenumbrüche (\n
) in Leerzeichen () zu ändern, und verrohrt, dass durch xargs in Ihrem Skript, bis es Schleifen nicht mehr Eingänge, von denen jeder Zugabe, können Sie eine Antwort haben.
Also, so etwas wie die folgenden:
cat <whatever> | cut -d'\t` -f7 | grep -v <appropriate-character-class> | tr '\n' ' ' | xargs script-that-adds-arguments
Ich kann die cut
Flaggen etwas falsch - aber man
ist dein Freund:)
Sie können es in jeder Online-awk Referenz nachschlagen:
ipcs | awk '
BEGIN { sum = 0 }
/0x000000/ { sum = sum + $2 }
END {print sum}'
Danke für den Python Einzeiler oben !. Es half mir zu leicht überprüfen Sie die belegte Speicherplatz auf meiner Festplatte. Hier ist eine Mischschale / Python one-liner, die dies tun - Zählungen verwendeten Speicherplatz auf dem Gerät / dev / SDA in Megabytes. Es dauerte einige Zeit, bevor ich es herausgefunden, so, vielleicht jemand auch dies nützlich findet.
df -h -B 1M | grep dev/sda | tr -s ' '| cut -d' ' -f3 |python -c "import sys; print sum([int(num) for num in sys.stdin.readlines()])"
oder mehr Python / weniger Shell:
df -h -B 1M | python -c "import sys; print sum([int(l.split()[2]) for l in sys.stdin.readlines() if '/dev/sda' in l])"
Danke nochmal!
Um Werte in einer Spalte summieren Sie GNU datamash verwenden können. Da die ersten vier Zeilen, die Sie zusammenfassen wollen keine Werte enthalten, entfernen wir sie mit tail +4
.
ipcs -mb | tail +4 | datamash -W sum 7
Die -W
Option stellt die Feldtrennzeichen (ggf. mehr) Leerzeichen.
Wenn Sie spezifische haben, mehrere Spalten, die Sie addieren möchten, können Sie:
input_command | awk '{s1+=$1;s2+=$2;s3+=$3;s4+=$4;s5+=$5}END{print s1,s2,s3,s4,s5}'
, die funktioniert, wenn Sie 1-5 Spalten summieren möchten.