Как выполнить многострочный 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 

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

В приведенном выше примере правильным ответом будет 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»?

  • Вставьте несколько строк после матча с помощью команды sed sed
  • SED Показывает CRLF, пока Vim не показывает
  • Добавить кавычки и новый разделитель вокруг слов, разделенных пробелами
  • Извлечь точное количество элементов из одного и того же идентификатора
  • Как удалить повторяющиеся слова с суффиксами?
  • умножение каждой строки
  • Каковы альтернативные инструменты для поиска файлов в полном объеме?
  • Захватить определенное содержимое файла
  • 8 Solutions collect form web for “Как выполнить многострочный grep”

    Если данные всегда в этом формате, вы можете просто написать его:

     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 

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

    Вот один из способов сделать это с помощью 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 , это не сработало бы.

    Смотрите также

    • Чтение абзаца за раз
    • PerlRun

    Если у вас есть данные фиксированной длины (фиксированная длина относится к числу строк в записи), в 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 

    … и вот решение 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. 
    Interesting Posts

    "/ Usr / lib / passmgmt: Файл паролей занят. Повторите попытку позже "в Solaris 11

    atop + что такое PAG на вершине

    Как скопировать содержимое папки с файлами при сохранении структуры папок?

    Как безопасно рандомизировать порядок символов в строке?

    Как заменить строку знаком доллара в sed?

    Лучшие практики для упаковки самостоятельно созданного программного обеспечения для Debian

    Какие другие параметры, кроме ifupdown, существуют для обычных пользователей / sys-admin?

    Могу ли я записывать звук до тишины или максимальной продолжительности записи?

    Сценарий проверки установленного пакета debian – обработка ошибок?

    Как узнать последнее время выполнения сценария оболочки?

    Почему / bin символическая ссылка на / usr / bin?

    Не удается смонтировать SD-карту. Неверная файловая система.

    механизм IP-алиаса

    В каких случаях команда, которую вы вводили, теряется из истории?

    аннотировать файл «include» для grep с комментариями?

    Linux и Unix - лучшая ОС в мире.