Я просто работал в к той же проблеме. Если это - та же проблема, у меня есть Вы, должен смочь решить его путем выбора пакета в синаптическом, то перейдите к Пакету> Версия Силы в меню и выберите новейшую версию.
Если данные всегда находятся в том формате, Вы могли бы просто записать это:
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}'
$ 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
Вот один способ сделать это использование 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
Ваш выходной формат запущен для абзаца Perl, хлебайте:
pbsnodes|perl -n00le 'BEGIN{ $sum = 0 }
m{
state \s* = \s* free \s* \n
procs \s* = \s* ([0-9]+)
}x
and $sum += $1;
END{ print $sum }'
Примечание:
Это только работает, потому что идея Perl "абзаца" является блоком непустых строк, разделенных одной или несколькими пустыми строками. Если у Вас не было пустых строк между node
разделы, это не работало бы.
См. также
Если у Вас есть данные фиксированной длины (фиксированная длина, относящаяся к количеству строк в записи), в 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
вероятно, получит Вас там более удобным путем.
Реализация GNU grep
идет с двумя аргументами, чтобы также распечатать строки прежде (-B
) и после (-A
) соответствие. Отрывок из страницы справочника:
-A NUM, --after-context=NUM
Print NUM lines of trailing context after matching lines. Places a line containing a group separator (--) between contiguous groups of matches. With the -o or
--only-matching option, this has no effect and a warning is given.
-B NUM, --before-context=NUM
Print NUM lines of leading context before matching lines. Places a line containing a group separator (--) between contiguous groups of matches. With the -o or
--only-matching option, this has no effect and a warning is given.
Таким образом в Вашем случае, Вы имели бы к grep для state = free
и также распечатайте следующую строку. При объединении этого с отрывками от вопроса Вы прибудете во что-то как этот:
usr@srv % pbsnodes | grep -A 1 'state = free' | grep "procs = " | awk '{ print $3 }' | awk '{ sum+=$1 } END { print sum }'
6
и немного короче:
usr@srv % pbsnodes | grep -A 1 'state = free' | awk '{ sum+=$3 } END { print sum }'
6
awk
делает сопоставление с образцом; Вам не нужно grep
: см. ответ Stephane
– jasonwryan
01.10.2013, 01:01
sed
делает сопоставление с образцом также. Вы могли также использовать perl
, или php
, или что когда-либо язык Вы предпочитаете. Но по крайней мере заголовок вопроса, который задают для много строки grep... прекрасный ;-)
– binfalse
01.10.2013, 01:18
... и вот решение для Perl:
pbsnodes | perl -lne 'if (/^\S+/) { $node = $& } elsif ( /state = free/ ) { print $node }'
Можно использовать awk
getline
команда :
$ pbsnodes | awk 'BEGIN { freeprocs = 0 } \
$1=="state" && $3=="free" { getline; freeprocs+=$3 } \
END { print freeprocs }'
От man awk
:
getline Set $0 from next input record; set NF, NR, FNR.
getline <file Set $0 from next record of file; set NF.
getline var Set var from next input record; set NR, FNR.
getline var <file Set var from next record of file.
command | getline [var]
Run command piping the output either into $0 or var, as above.
command |& getline [var]
Run command as a co-process piping the output either into $0 or var, as above. Co-processes are a
gawk extension.