So subtrahieren Sie Zeilen (Linien) mit AWK

9

Ich versuche herauszufinden, wie ich AWK verwenden kann, um Linien zu subtrahieren. Stellen Sie sich zum Beispiel vor, die Eingabedatei lautet:

30
20

Die Ausgabe wäre:

10

Als Test versuche ich nun, die "Used" -Speicherspalte zu berechnen aus:

$ cat /proc/meminfo

Im Moment habe ich folgendes geschrieben:

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    -- Here comes the calculation using AWK

Ich habe folgendes versucht:

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}' | awk '{$0-s}{s=$0} END {print s}' 

Dies gibt mir jedoch nur die letzte Datenzeile.

Ich habe eine funktionierende Lösung gefunden, aber ich bezweifle, dass es die optimalste ist. Alle meine Codierungserfahrungen zeigen mir, dass die harte Codierung der Anzahl der Zeilen schrecklich ist: P.

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}' | awk 'NR == 1{s=$0} NR == 2 {s=s-$0} END {print s}'
Dylan Meeus
quelle
Was möchten Sie mit N Zeilen tun? Sollte das Endergebnis sein line1_$2 - line2_$2 - lineN-$2? Möchten Sie nur die ersten beiden aufeinander folgenden Zeilen subtrahieren?
Terdon

Antworten:

9

Sie können dies auch tun mit awk, pasteund bc. Ich finde diesen Ansatz leichter zu merken. Die Syntax von awkerfordert immer, dass ich nachschaue, um ihn zu bestätigen.

HINWEIS: Dieser Ansatz hat den Vorteil, dass er mit mehreren Ausgabezeilen konkurrieren kann und die 2., 3., 4. usw. Zahlen von der 1. subtrahiert.

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}' | paste -sd- - | bc
7513404

Einzelheiten

Mit dem obigen awkBefehl wird die Spalte ausgewählt, die die Zahlen enthält, die subtrahiert werden sollen.

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}'
7969084
408432

Wir verwenden dann paste, um diese 2 Wertewerte zu kombinieren und das Minuszeichen dazwischen hinzuzufügen.

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}'| paste -sd- -
7969084-346660

Wenn wir dies übergeben, bcführt es die Berechnung durch.

$ grep -P 'MemTotal|MemFree' /proc/meminfo | \
    awk '{print $2}'| paste -sd- - | bc
7513404
slm
quelle
@terdon - danke, dass ich diese Bearbeitung vorgenommen habe, als du sie gemacht hast 8-)
slm
3

Die rein awk-Lösung, keine redundanten Cat- oder Grep-Befehle:

awk '/MemTotal/ {TOT=$2} /MemFree/ {FREE=$2} END {printf("%d kB Used\n", TOT-FREE)}' /proc/meminfo

Ich sehe, dass awk_FTW mich geschlagen hat, aber ich dachte, das Formatieren der Ausgabe könnte nett sein.

Johan
quelle
3

Versuche dies:

grep -P 'MemTotal|MemFree' /proc/meminfo | \
awk 'NR==1{s=$2;next}{s-=$2}END{print s}'
cuonglm
quelle