I have a command that outputs information about all DIMM slots in blocks like the following:

44    105  SMB_TYPE_MEMDEVICE (type 17) (memory device)

  Manufacturer: NO DIMM
  Serial Number: NO DIMM
  Asset Tag: NO DIMM
  Location Tag: P1-DIMMD1
  Part Number: NO DIMM

  Physical Memory Array: 43
  Memory Error Data: Not Supported
  Total Width: 0 bits
  Data Width: 0 bits
  Size: Not Populated
  Form Factor: 9 (DIMM)
  Set: None
  Rank: Unknown
  Memory Type: 2 (unknown)
  Flags: 0x4
        SMB_MDF_UNKNOWN (unknown)
  Speed: Unknown
  Configured Speed: Unknown
  Device Locator: P1-DIMMD1
  Bank Locator: P0_Node1_Channel0_Dimm0
  Minimum Voltage: 1.20V
  Maximum Voltage: 1.20V
  Configured Voltage: 1.20V

The blocks start with the ID SIZE TYPE header and end with the configured voltage information. The command outputs one of these blocks of data for each DIMM separated by a single blank line each.

I would like to be able to get the block of information for a specific DIMM slot based on the Location Tag field, but am unsure how to go about it. I am pretty sure this can be done with awk but only know how to print the match awk '/P1-DIMMD1/' or the line prior to match awk '/P1-DIMMD1/ {print a}{a=$0}'

Does anyone know how I could extract this whole block of data if the Location Tag matches my search (P1-DIMMD1)?


3 Answers 3


The following will match the tag given in the tag variable:

awk -v tag=P1-DIMMD1 '/ID    SIZE TYPE/ { block = $0; output = 0; next } { block = block "\n" $0 } /Location Tag/ { output = ($0 ~ tag) } /Configured Voltage/ && output { print block }'

The AWK script is

  block = $0
  output = 0

{ block = block "\n" $0 }

/Location Tag/ { output = ($0 ~ tag) }

/Configured Voltage/ && output { print block }

We accumulate a block in the block variable, and output it when we reach the end of the block if we saw the right tag in the process.


You could use ed ... and sed, man!

You have to want to use ed for this one, though, as ed wants to operate on a file, not as part of a pipeline.

  1. command > dimm-output
  2. wanted=P1-DIMMD1
  3. ed -s dimm-output <<< $'/Location Tag: '"$wanted"$'\n?^ID.*SIZE.*TYPE\n.,/Configured Voltage/p\nq\n' | sed 1,2d

The ed command-string breaks down to four \n-separated commands:

  1. search forwards, using /, for the text "Location Tag: " followed by the value of the $wanted variable
  2. search backwards, using ?, for the pattern: (start-of-line), "ID", anything, "SIZE", anything, "TYPE"
  3. from that line (.), through (,) the next line that matches "Configured Voltage", print those lines (p)
  4. quit ed: q

Because ed auto-prints the matching line when you search, I used sed here to delete those two lines.


Inspired by @Stephen Kitts great answer, I wrote a little more general script to perform block matching when having a specified start and end pattern.

#!/usr/bin/awk -f
$0 ~ pstart { block = $0; output = 0; next }
{ block = block "\n" $0 }
$0 ~ pmatch { output = 1 }
$0 ~ pstop && output { print block; output = 0 }

Usage: match_block START END MATCH [FILE]

./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1' f


command | ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1'

Thanks for suggesting writing this as an awk script directly. My original shell script was:


[ -z "$4" ] && file="-" || file="$4"

awk \
  $0 ~ BLOCKSTART_PATTERN { block = $0; output = 0; next }
  { block = block "\n" $0 }
  $0 ~ BLOCKMATCH_PATTERN { output = 1 }
  $0 ~ BLOCKEND_PATTERN && output { print block; output = 0 }
  ' "$file"

Usage: match_block START END MATCH [FILE].
If file is omitted, stdin will be used.

In your case:

command | ./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1'


./match_block '^ID' 'Configured Voltage' 'Location Tag: P1-DIMMD1' file

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .