Как выполнить многострочный grep

Как выполнить многострочный grep

Как бы вы выполнили grep для текста, который находится в двух строках?

Например:

pbsnodesэто команда, которую я использую, чтобы вернуть использование кластера Linux

root$ pbsnodes
node1
    state = free
    procs = 2
    bar = foobar

node2
    state = free
    procs = 4
    bar = foobar

node3
    state = busy
    procs = 8
    bar = foobar

Я хочу определить количество процессов, соответствующих узлам, которые находятся в состоянии «свободно». До сих пор мне удавалось определить «количество процессов» и «узлы в свободном состоянии», но я хочу объединить их в одну команду, которая показывает все свободные процессы.

В приведенном выше примере правильным ответом будет 6 (2+4).

Что у меня есть

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

Как мне выполнить поиск по каждой строке, в которой указано «procs = x», но только если строка над ней содержит «state = free»?

решение1

Если данные всегда имеют такой формат, вы можете просто записать их:

awk -vRS= '$4 == "free" {n+=$7}; END {print n}'

( RS=означаетзаписи — это абзацы).

Или:

awk -vRS= '/state *= *free/ && match($0, "procs *=") {
  n += substr($0,RSTART+RLENGTH)}; END {print n}'

решение2

$ 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)

решение3

Вот один из способов сделать это с помощью pcregrep.

$ pbsnodes | pcregrep -Mo 'state = free\n\s*procs = \K\d+'
2
4

Пример

$ pbsnodes | \
    pcregrep -Mo 'state = free\n\s*procs = \K\d+' | \
    awk '{ sum+=$1 }; END { print sum }'
6

решение4

Если у вас есть данные фиксированной длины (фиксированная длина относится к количеству строк в записи), sedвы можете использовать Nкоманду (несколько раз), которая присоединяет следующую строку к пространству шаблона:

sed -n '/^node/{N;N;N;s/\n */;/g;p;}'

должен дать вам такой вывод:

node1;state = free;procs = 2;bar = foobar
node2;state = free;procs = 4;bar = foobar
node3;state = busy;procs = 8;bar = foobar

Для создания переменной записи (например, с пустой разделительной линией) можно использовать команды ветвления tи b, но, awkскорее всего, это позволит вам добиться цели более удобным способом.

Связанный контент