
次のように、すべての 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 つを、それぞれ 1 つの空白行で区切って出力します。
フィールドに基づいて特定のDIMMスロットの情報ブロックを取得できるようにしたいのですLocation Tag
が、その方法がわかりません。これは実行できることは確かですが、一致または一致の前の行awk
を印刷する方法しか知りません。awk '/P1-DIMMD1/'
awk '/P1-DIMMD1/ {print a}{a=$0}'
Location Tag
が検索条件 ( P1-DIMMD1
)と一致する場合、このデータ ブロック全体を抽出する方法を知っている人はいますか?
答え1
以下は、タグ変数で指定されたタグと一致します。
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 を使用します。
command > dimm-output
wanted=P1-DIMMD1
ed -s dimm-output <<< $'/Location Tag: '"$wanted"$'\n?^ID.*SIZE.*TYPE\n.,/Configured Voltage/p\nq\n' | sed 1,2d
コマンドed
文字列は、 で区切られた 4 つのコマンドに分割されます\n
。
- を使って前方検索し、
/
テキスト「Location Tag:」の後に$wanted
変数の値が続くものを検索する。 - , を使用して、パターンを後方に検索します
?
: (行頭)、"ID"、任意の文字、"SIZE"、任意の文字、"TYPE" - その行(
.
)から,
「設定された電圧」に一致する次の行( )まで、それらの行を印刷します(p
) - 終了 ed:
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