Search code examples
awkfreebsd

Getting awk to print a line with a keyword, but only within a range


I am using FreeBSD's geom command to gather information about partitions on my storage devices and filter it using awk. Specifically, I'm trying to extract two lines from the Providers section of the output: Mediasize, and type.

This is what the unfiltered output looks like:

$ 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

I can use this awk one-liner to get Mediasize and type, but it returns both the Providers and Consumers Mediasize: since the search string appears in both sections:

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

I can use this command to limit the output to only the lines that fall between Providers: and Consumers:

$ 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:

What I'm struggling with is how to combine the two into an awk one-liner, to print Mediasize:, but only from the Providers: section.

I've tried this, but it gives me errors:

$ 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

Piping the output of one awk program to another gets me what I want, but it seems like a kludge.

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

Ideally, I'd like to get the output from a single awk one-liner.

Ways I can think of (ordered from most elegant to least elegant) include:

1) Somehow fixing awk '/Providers:/,/Consumers:/ { /Mediasize:/ { print $2 } /[ ]+type:/ { print $2 } }'

2) Exiting premeturely once the Consumers: keyword is encountered.

3) Using a flag to toggle printing off once the Consumers: keyword is encountered.

I can get #3 to work, with a flag and a ternary operator, but it seems less than elegant:

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

Any ideas on how I might get solution #1 or #2 to work, or perhaps another solution I am overlooking?


Solution

  • Untested:

    /Mediasize/ { print $2 }
    /type/      { print $2 }
    /Consumers/ { exit }