一致する場合、複数行の抽出

一致する場合、複数行の抽出

次のように、ブロック内のすべてのDIMMスロットに関する情報を出力するコマンドがあります。

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

これらのブロックはID SIZE TYPEヘッダで始まり、設定された電圧情報で終わります。このコマンドは、各 DIMM についてこれらのデータブロックの 1 つを出力します。各ブロックは空行で区切られます。


このフィールドに基づいて特定のDIMMスロットに関する情報の集まりを取得したいのですLocation Tagが、どうすればよいかわかりません。これは可能であると確信していますが、一致項目または一致項目の前にある行をawk印刷する方法だけを知ることができます。awk '/P1-DIMMD1/'awk '/P1-DIMMD1/ {print a}{a=$0}'

Location Tag私のsearch()と一致する場合は、データの全体を抽出する方法を知っている人はいますかP1-DIMMD1

答え1

以下は、label変数で指定されたラベルと一致します。

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

AWKスクリプトは次のとおりです。

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

{ block = block "\n" $0 }

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

/Configured Voltage/ && output { print block }

変数にチャンクを蓄積しblock、プロセス中に正しいラベルが表示された場合、チャンクの終わりに達したときにそれを出力します。

答え2

あなたはできますEdを使う...そしてセド、友達!

あなたはする必要があります考えるただし、edはパイプラインの一部ではないファイルで作業したいので、それを処理するにはedを使用してください。

  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

コマンド文字列は4つの別々のコマンドedに分けられます。\n

  1. 「位置タグ:」テキストと変数の/値を使用して前方に検索します。$wanted
  2. 使用、リバース検索?パターン:(行の先頭)、「ID」、any、「SIZE」、any、「TYPE」
  3. このライン(.)から(,)までの「構成電圧」に一致する次のラインを印刷します(p)。
  4. 修正終了:q

edは検索時に一致する行を自動的に印刷するため、sedここではこれら2行を削除します。

答え3

@Stephen Kittsの素晴らしい答えからインスピレーションを得て、指定された開始パターンと終了パターンがあるときにブロックマッチングを実行するより一般的なスクリプトを作成しました。

#!/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 }

使用法: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'

awkスクリプトを直接作成することを提案していただきありがとうございます。私の元のシェルスクリプトは次のとおりです。

#!/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"

使用法: match_block START END MATCH [FILE]
ファイルを省略すると、stdinそのファイルが使用されます。

あなたの場合:

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

または

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

関連情報