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
War es hilfreich?

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:

  1. grep die Linien, die die Zahlen
  2. enthalten
  3. sed entfernt alle Zeichen vor (und nach) der Nummer auf jeder Zeile
  4. xargs das Ergebnis
  5. (eine Reihe von Zahlen durch Leerzeichen getrennt zu bekommen)
  6. tr anslate die Rohlinge auf '+' Zeichen
  7. 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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top