Wie würden Sie ein Grep für Text ausführen, der über zwei Zeilen erscheint?
Zum Beispiel:
pbsnodes
ist ein von mir verwendeter Befehl, der die Auslastung eines Linux-Clusters zurückgibt
root$ pbsnodes
node1
state = free
procs = 2
bar = foobar
node2
state = free
procs = 4
bar = foobar
node3
state = busy
procs = 8
bar = foobar
Ich möchte die Anzahl der Prozesse ermitteln, die mit Knoten übereinstimmen, die sich im Status „frei“ befinden. Bisher konnte ich die „Anzahl der Prozesse“ und „die Knoten im freien Status“ ermitteln, aber ich möchte sie in einem Befehl kombinieren, der alle freien Prozesse anzeigt.
Im obigen Beispiel wäre die richtige Antwort 6 (2+4).
Was ich habe
root$ NUMBEROFNODES=`pbsnodes|grep 'state = free'|wc -l`
root$ echo $NUMBEROFNODES
2
root$ NUMBEROFPROCS=`pbsnodes |grep "procs = "|awk '{ print $3 }' | awk '{ sum+=$1 } END { print sum }'`
root$ echo $NUMBEROFPROCS
14
Wie kann ich nach jeder Zeile suchen, in der „procs = x“ steht, aber nur, wenn in der Zeile darüber „state = free“ steht?
Antwort1
Wenn die Daten immer in diesem Format vorliegen, können Sie sie einfach wie folgt schreiben:
awk -vRS= '$4 == "free" {n+=$7}; END {print n}'
( RS=
bedeutetDatensätze sind Absätze).
Oder:
awk -vRS= '/state *= *free/ && match($0, "procs *=") {
n += substr($0,RSTART+RLENGTH)}; END {print n}'
Antwort2
$ pbsnodes
node1
state = free
procs = 2
bar = foobar
node2
state = free
procs = 4
bar = foobar
node3
state = busy
procs = 8
bar = foobar
$ pbsnodes | grep -A 1 free
state = free
procs = 2
--
state = free
procs = 4
$ pbsnodes | grep -A 1 free | grep procs | awk '{print $3}'
2
4
$ pbsnodes | grep -A 1 free | grep procs | awk '{print $3}' | paste -sd+
2+4
$ pbsnodes | grep -A 1 free | grep procs | awk '{print $3}' | paste -sd+ | bc
6
Antwort3
Hier ist eine Möglichkeit, dies zu tun pcregrep
.
$ pbsnodes | pcregrep -Mo 'state = free\n\s*procs = \K\d+'
2
4
Beispiel
$ pbsnodes | \
pcregrep -Mo 'state = free\n\s*procs = \K\d+' | \
awk '{ sum+=$1 }; END { print sum }'
6
Antwort4
Wenn Sie Daten mit fester Länge haben (mit fester Länge ist die Anzahl der Zeilen in einem Datensatz gemeint), sed
können Sie den Befehl (mehrmals) verwenden N
, der die nächste Zeile an den Musterbereich anfügt:
sed -n '/^node/{N;N;N;s/\n */;/g;p;}'
Sie sollten eine Ausgabe wie die folgende erhalten:
node1;state = free;procs = 2;bar = foobar
node2;state = free;procs = 4;bar = foobar
node3;state = busy;procs = 8;bar = foobar
Für die variable Datensatzzusammenstellung (z. B. mit einer leeren Trennzeile) könnten Sie die Verzweigungsbefehle t
und verwenden b
, aber awk
wahrscheinlich gelangen Sie auf komfortablere Weise dorthin.