Как бы вы выполнили 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
решение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
скорее всего, это позволит вам добиться цели более удобным способом.