我有一个命令可以输出有关块中所有 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 输出这些数据块之一,每个数据块之间由一个空行分隔。
我希望能够根据该Location Tag
字段获取特定 DIMM 插槽的信息块,但我不确定如何进行。我很确定这可以完成,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...和sed,伙计!
你必须想不过,要使用 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
字符串分为四个\n
分隔的命令:
- 使用 向前搜索文本“位置标记:”,后跟变量
/
值$wanted
- 使用 , 向后搜索
?
模式:(行首)、“ID”、任何内容、“SIZE”、任何内容、“TYPE” - 从该行 (
.
) 到 (,
) 与“配置电压”匹配的下一行,打印这些行 (p
) - 退出编辑:
q
因为 ed 在搜索时会自动打印匹配行,所以我sed
在这里使用删除这两行。
答案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
直接将其编写为脚本。我原来的 shell 脚本是:
#!/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