Получение awk для печати строки с ключевым словом, но только в пределах диапазона - PullRequest
1 голос
/ 22 марта 2020

Я использую команду geom FreeBSD для сбора информации о разделах на моих устройствах хранения и фильтрации ее с помощью awk. В частности, я пытаюсь извлечь две строки из раздела «Поставщики» вывода: Mediasize и тип.

Вот как выглядит нефильтрованный вывод:

$ geom part list da0
Geom name: da0
modified: false
state: OK
fwheads: 255
fwsectors: 63
last: 120845263
first: 40
entries: 128
scheme: GPT
Providers:
1. Name: da0p1
   Mediasize: 61872754688 (58G)
   Sectorsize: 512
   Stripesize: 0
   Stripeoffset: 20480
   Mode: r0w0e0
   efimedia: HD(1,GPT,1b5fe285-3be5-11ea-8179-b827ebb30e4e,0x28,0x733f3a8)
   rawuuid: 1b5fe285-3be5-11ea-8179-b827ebb30e4e
   rawtype: 516e7cb6-6ecf-11d6-8ff8-00022d09712b
   label: (null)
   length: 61872754688
   offset: 20480
   type: freebsd-ufs
   index: 1
   end: 120845263
   start: 40
Consumers:
1. Name: da0
   Mediasize: 61872793600 (58G)
   Sectorsize: 512
   Mode: r0w0e0

Я могу использовать этот awk однострочный, чтобы получить Mediasize и тип, но он возвращает Mediasize как поставщиков, так и потребителей: поскольку строка поиска отображается в обоих разделах:

$ geom part list da0 | awk '/Mediasize:/ { print $2 } /[ ]+type:/ { print $2 }'
61872754688
freebsd-ufs
61872793600

Я могу использовать эту команду, чтобы ограничить вывод только линии, которые проходят между провайдерами: и потребителями:

$ geom part list da0 | awk '/Providers:/,/Consumers:/'
Providers:
1. Name: da0p1
   Mediasize: 61872754688 (58G)
   Sectorsize: 512
   Stripesize: 0
   Stripeoffset: 20480
   Mode: r0w0e0
   efimedia: HD(1,GPT,1b5fe285-3be5-11ea-8179-b827ebb30e4e,0x28,0x733f3a8)
   rawuuid: 1b5fe285-3be5-11ea-8179-b827ebb30e4e
   rawtype: 516e7cb6-6ecf-11d6-8ff8-00022d09712b
   label: (null)
   length: 61872754688
   offset: 20480
   type: freebsd-ufs
   index: 1
   end: 120845263
   start: 40
Consumers:

С чем я борюсь, так это как объединить два в одну строку awk, чтобы вывести Mediasize :, но только из раздела провайдеров: .

Я пробовал это, но это дает мне ошибки:

$ geom part list da0 | awk '/Providers:/,/Consumers:/ { /Mediasize:/ { print $2 } /[ ]+type:/ { print $2 } }'
awk: syntax error at source line 1
 context is
        /Providers:/,/Consumers:/ { /Mediasize:/ >>>  { <<<
awk: illegal statement at source line 1
awk: syntax error at source line 1

Передача выходных данных одной awk-программы в другую дает мне то, что я хочу, но это похоже на kludge.

$ geom part list da0 | awk '/Providers:/,/Consumers:/' | awk '/Mediasize:/ { print $2 } /[ ]+type:/ { print $2 }'
61872754688
freebsd-ufs

В идеале, я хотел бы получить выходные данные из одного awk-однострочного.

Пути, которые я могу придумать (от самых элегантных до наименее элегантных), включают:

1) Как-то исправление awk '/ Providers: /, / Consumers: / {/ Mediasize: / {print $ 2} / [] + type: / {print $ 2}}'

2) Преждевременный выход из системы при обнаружении ключевого слова Consumers :.

3) Использование флага для переключения печати при обнаружении ключевого слова «Потребители:».

Я могу заставить работать # 3, с флагом и троичным оператором, но кажется, что меньше элегантный:

$ geom part list da0 | awk '/Mediasize:/ { print (++flag==1)?$2:"" } /[ ]type:/ { print (flag==1)?$2:"" }'
61872754688
freebsd-ufs

Есть идеи, как можно заставить работать решение № 1 или № 2, или, возможно, другое решение, которое я пропускаю?

Ответы [ 3 ]

1 голос
/ 15 апреля 2020

Вы можете использовать флаг , например:

awk '/Providers/ {f=1; next} f && /Mediasize/{print $2; f=0}

Это можно прочитать как после сопоставления Providers, найти Mediazise и вернуть второе поле.

1 голос
/ 22 марта 2020

Не проверено:

/Mediasize/ { print $2 }
/type/      { print $2 }
/Consumers/ { exit }
0 голосов
/ 22 марта 2020

Для тех, кто заинтересован в конечном результате, я смог применить ответ пользователя user448810 и получить желаемый вывод.

Команда:

geom part list mmcsd0 | awk 'BEGIN { printf "{" } /Name/ { printf "%s\n  \"%s\": { ", (++count==1)?"":",", $3 } /Mediasize/ { printf "\"size\": %s, ", $2 } / type:/ { printf "\"type\": \"%s\" }", $2 } /Consumers/ { exit } END { printf "\n}\n" }'

Вывод:

{
  "mmcsd0s1": { "size": 52383744, "type": "fat32lba" },
  "mmcsd0s2": { "size": 31052026368, "type": "freebsd" }
}

Qué Bello!

...