Extraia várias linhas se corresponder

Extraia várias linhas se corresponder

Eu tenho um comando que gera informações sobre todos os slots DIMM em blocos como o seguinte:

ID    SIZE TYPE
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

Os blocos começam com o ID SIZE TYPEcabeçalho e terminam com as informações de tensão configuradas. O comando gera um desses blocos de dados para cada DIMM separados por uma única linha em branco cada.


Gostaria de obter o bloco de informações para um slot DIMM específico com base no Location Tagcampo, mas não tenho certeza de como fazer isso. Tenho certeza de que isso pode ser feito, awkmas só sei como imprimir a correspondência awk '/P1-DIMMD1/'ou a linha antes da correspondênciaawk '/P1-DIMMD1/ {print a}{a=$0}'

Alguém sabe como eu poderia extrair todo esse bloco de dados se Location Tagcorresponder à minha pesquisa ( P1-DIMMD1)?

Responder1

O seguinte corresponderá à tag fornecida na variável tag:

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 }'

O script AWK é

/ID    SIZE TYPE/ {
  block = $0
  output = 0
  next
}

{ block = block "\n" $0 }

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

/Configured Voltage/ && output { print block }

Acumulamos um bloco na blockvariável e o geramos quando chegamos ao final do bloco se vimos a tag correta no processo.

Responder2

Você poderiausar...esim, cara!

Você tem quequererusar ed para este, porém, já que ed deseja operar em um arquivo, não como parte de um 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

A edsequência de comandos se divide em quatro \ncomandos separados:

  1. pesquise para frente, usando /, o texto "Location Tag:" seguido do valor da $wantedvariável
  2. pesquise para trás, usando ?, pelo padrão: (início da linha), "ID", qualquer coisa, "TAMANHO", qualquer coisa, "TIPO"
  3. dessa linha ( .), até ( ,) a próxima linha que corresponde a "Tensão configurada", imprima essas linhas ( p)
  4. sair ed:q

Como ed imprime automaticamente a linha correspondente quando você pesquisa, usei sedaqui para excluir essas duas linhas.

Responder3

Inspirado pela ótima resposta de @Stephen Kitts, escrevi um script um pouco mais geral para realizar a correspondência de blocos ao ter um padrão de início e fim especificado.

#!/usr/bin/awk -f
BEGIN {
    pstart=ARGV[1];
    pstop=ARGV[2];
    pmatch=ARGV[3];
    ARGV[1]=ARGV[4];
    ARGC=2;
}
$0 ~ pstart { block = $0; output = 0; next }
{ block = block "\n" $0 }
$0 ~ pmatch { output = 1 }
$0 ~ pstop && output { print block; output = 0 }

Uso:match_block START END MATCH [FILE]

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

ou

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

Obrigado por sugerir escrever isso awkdiretamente como um script. Meu script de shell original era:

#!/bin/sh

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

awk \
  -v BLOCKSTART_PATTERN="$1" \
  -v BLOCKEND_PATTERN="$2" \
  -v BLOCKMATCH_PATTERN="$3" \
  '
  $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"

Uso: match_block START END MATCH [FILE].
Se o arquivo for omitido, stdinserá usado.

No seu caso:

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

ou

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

informação relacionada