¿Cómo realizarías un grep para un texto que aparece en dos líneas?
Por ejemplo:
pbsnodes
es un comando que uso que devuelve la utilización de un clúster de Linux
root$ pbsnodes
node1
state = free
procs = 2
bar = foobar
node2
state = free
procs = 4
bar = foobar
node3
state = busy
procs = 8
bar = foobar
Quiero determinar la cantidad de procesos que coinciden con los nodos que están en estado "libre". Hasta ahora he podido determinar el "número de procesos" y "los nodos en estado libre", pero quiero combinarlos en un comando que muestre todos los procesos libres.
En el ejemplo anterior, la respuesta correcta sería 6 (2+4).
Lo que tengo
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
¿Cómo puedo buscar cada línea que dice 'procs = x', pero solo si la línea de arriba dice 'state = free?
Respuesta1
Si los datos siempre están en ese formato, simplemente podrías escribirlos:
awk -vRS= '$4 == "free" {n+=$7}; END {print n}'
( RS=
mediolos registros son párrafos).
O:
awk -vRS= '/state *= *free/ && match($0, "procs *=") {
n += substr($0,RSTART+RLENGTH)}; END {print n}'
Respuesta2
$ 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
Respuesta3
Esta es una manera de hacerlo usando pcregrep
.
$ pbsnodes | pcregrep -Mo 'state = free\n\s*procs = \K\d+'
2
4
Ejemplo
$ pbsnodes | \
pcregrep -Mo 'state = free\n\s*procs = \K\d+' | \
awk '{ sum+=$1 }; END { print sum }'
6
Respuesta4
Si tiene datos de longitud fija (longitud fija que se refiere al número de líneas en un registro), sed
puede usar el N
comando (varias veces), que une la siguiente línea al espacio del patrón:
sed -n '/^node/{N;N;N;s/\n */;/g;p;}'
debería darte resultados como:
node1;state = free;procs = 2;bar = foobar
node2;state = free;procs = 4;bar = foobar
node3;state = busy;procs = 8;bar = foobar
Para una composición de registros variable (por ejemplo, con una línea separadora vacía), puede utilizar comandos de bifurcación t
y b
, pero awk
es probable que le lleve allí de una forma más cómoda.