So führen Sie ein mehrzeiliges Grep durch

So führen Sie ein mehrzeiliges Grep durch

Wie würden Sie ein Grep für Text ausführen, der über zwei Zeilen erscheint?

Zum Beispiel:

pbsnodesist 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

https://en.wikipedia.org/wiki/Pipeline_(Unix)

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), sedkö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 tund verwenden b, aber awkwahrscheinlich gelangen Sie auf komfortablere Weise dorthin.

verwandte Informationen