英文:
Getting Specific Value from Dmidecode Output with Bash Script
问题
Expected output: 00000020
你的 bash 脚本已经可以达到你的预期输出,但是你可以稍微简化一下。以下是一个更简洁的版本:
#!/bin/bash
expected_id="00000020"
dmidecode_output=$(dmidecode -t 219)
hex_string=$(echo "$dmidecode_output" | grep -o -P "01 85 30 \K[0-9a-fA-F]{8}")
if [ "$hex_string" == "$expected_id" ]; then
echo "1"
else
echo "0"
fi
这个脚本会提取 dmidecode 输出中与 "01 85 30" 后面的八个十六进制字符匹配的部分,然后与预期的输出进行比较,最终输出 1 或 0,取决于它们是否匹配。
英文:
Below is a section from the dmidecode output. There is a part of this section that I want to break down. I want to get the 4 bytes after pattern 01 85 30. And I want to change the byte order. Then I will compare with the hex strings I have.
.......
Handle 0x0027, DMI type 219, 106 bytes
OEM-specific Type
Header and Data:
DB 6A 27 00 01 04 01 45 02 00 90 06 *01 85 30* 20
00 00 00 00 40 00 00 03 1F 24 02 C9 02 60 44 02
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF 03 00 00 00 80 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 04 FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF
.......
Expected output : 00000020
I prepared a bash script and it works, is there a better way?
#!/bin/bash
id_array=("00000020", "00000040")
unique_id=$(dmidecode -t 219 | grep "01 85 30" -A 1 | xargs | cut -c 46-56 | tr -d '[:space:]' | grep -o .. | tac | paste -sd '' -)
if [[ " ${id_array[*]} " == *"$unique_id"* ]];
then
echo "1"
else
echo "0"
fi
答案1
得分: 1
我会使用 GNU AWK
来执行此任务,以下是使用 command
输出的操作:
Handle 0x0027, DMI type 219, 106 bytes
OEM-specific Type
Header and Data:
DB 6A 27 00 01 04 01 45 02 00 90 06 01 85 30 20
00 00 00 00 40 00 00 03 1F 24 02 C9 02 60 44 02
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF 03 00 00 00 80 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 04 FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF
.......
然后
command | awk 'BEGIN{RS="01[[:space:]]85[[:space:]]30"}NR>1{print $4 $3 $2 $1}'
得到输出:
00000020
解释:我告知 GNU AWK,行分隔符(`RS`)是给定的序列,我使用 `[[:space:]]` 而不只是空格,以允许序列跨多行的情况,然后对于除第一行之外的每一行,我打印第四个字段与第三个字段以及第二个字段与第一个字段连接在一起。
(*在 GNU Awk 5.0.1 中测试过*)
<details>
<summary>英文:</summary>
I would harness GNU `AWK` for this task following, let `command` give output
Handle 0x0027, DMI type 219, 106 bytes
OEM-specific Type
Header and Data:
DB 6A 27 00 01 04 01 45 02 00 90 06 01 85 30 20
00 00 00 00 40 00 00 03 1F 24 02 C9 02 60 44 02
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF 03 00 00 00 80 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 04 FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF
.......
then
command | awk 'BEGIN{RS="01[[:space:]]85[[:space:]]30"}NR>1{print $4 $3 $2 $1}'
gives output
00000020
Explanation: I inform GNU AWK that row separator (`RS`) is given sequence, I use `[[:space:]]` rather than just space to allow situations when sequence does go through multiple lines, then for each line beyond 1st I print 4th field concatenated with 3rd field with 2nd field with 1st field.
*(tested in GNU Awk 5.0.1)*
</details>
# 答案2
**得分**: 0
这是提供的AWK解决方案,允许处理可能会破坏搜索模式和所寻找的字节值的换行符。
**整个过程**(`file` 包含原始数据)
```awk 'BEGIN{ORS=" "; OFS=" "} {gsub(FS," ",$0); $1=$1; print$0}' file | awk -v pattern="01 85 30" 'BEGIN{RS=pattern} NR==2{print $4" "$3" "$2" "$1}'
输出
00 00 00 20
部分 1
这部分将数据文件 file
重新格式化,以产生一个输出,其中输入文件的每个以空白分隔的 'word' 现在都由单个空格分隔。
这是通过在 BEGIN
块中将输出记录分隔符 ORS
和输出字段分隔符 OFS
都设置为单个空格来实现的。然后,在主块中,使用 gsub(FS," ",$0)
将每个记录中的默认输入字段分隔符 FS
(任意长度的空白)替换为单个空格字符。记录(行)然后被打印(print $0
)在强制 AWK 重新评估它(使用 $1=$1
)以防止行以原样传递。
第一部分的输出是:
Handle 0x0027, DMI type 219, 106 bytes OEM-specific Type Header and Data: DB 6A 27 00 01 04 01 45 02 00 90 06 01 85 30 20 00 00 00 00 40 00 00 03 1F 24 02 C9 02 60 44 02 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 03 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
并直接传输到第二个 AWK 过程
部分 2
使用变量标志 v
将搜索模式传递给 AWK 过程 -v pattern="01 85 30"
,这允许如果要处理许多模式(通过将模式设置为 shell 变量并在字符串"01 85 30"的位置使用变量名)的话,可以从 shell 命令中重复调用组合的过程。
一个 BEGIN
块将记录分隔符设置为传递的模式(RS=pattern
),以便后续块将文件的两侧的块作为单独的记录进行检查。
由于所需数据紧跟在模式之后,我们只对第二条记录感兴趣,因此主 AWK 块筛选第 2 条记录(NR==2
),以逆序打印前四个字段,用单个空格分隔,使用 print $4" "$3" "$2" "$1
。
英文:
Awk
solution allowing for line breaks that might disrupt the search pattern and the byte values being sought.
I've used two short awk procedures pipped together. The first formats the data such that the search pattern and following bytes are always separated by a single space, without line breaks, or any tabs or runs of spaces.
The second procedure divides the data at the now clean pattern set and extracts the first four bytes of the second record (the part immediately following the pattern), and prints them in reverse order.
whole procedure (file
contains the original data)
awk 'BEGIN{ORS=" "; OFS=" "} {gsub(FS," ",$0); $1=$1; print$0}' file | awk -v pattern="01 85 30" 'BEGIN{RS=pattern} NR==2{print $4" "$3" "$2" "$1}'
output
00 00 00 20
Explanation of parts
part 1
takes the data file file
and re-formats to produce an output that contains each white-space separated 'word' of the input file but now separated by a single space.
awk 'BEGIN{ORS=" "; OFS=" "} {gsub(FS," ",$0); $1=$1; print$0}' file |
This is achieved by setting both the output record separator ORS
and output field separator OFS
to a single space in the BEGIN
block. The main block then substitutes the default input field separatorFS
(white space of any length) for a single space character in each record, using gsub(FS," ",$0);
. The record (line) is then printed (print $0
) after forcing awk to reevaluate it (using $1=$1
) to prevent the line being passed as it was received.
The output of the first part is:
Handle 0x0027, DMI type 219, 106 bytes OEM-specific Type Header and Data: DB 6A 27 00 01 04 01 45 02 00 90 06 01 85 30 20 00 00 00 00 40 00 00 03 1F 24 02 C9 02 60 44 02 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 03 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
and is piped directly to the second awk procedure
part 2
| awk -v pattern="01 85 30" 'BEGIN{RS=pattern} NR==2{print $4" "$3" "$2" "$1}'
uses the variable flag v
to pass the search pattern into the awk procedure -v pattern="01 85 30"
allowing the combined procedure to be called repeatedly from a shell command if many patterns are to be processed (by setting the pattern to a shell variable and using the variable name in place of the string "01 85 30").
A BEGIN
block sets the record separator to be the passed pattern (RS=pattern
) so that subsequent blocks will examine chunks of the file either side of the pattern as individual records.
Since the required data immediately follows the pattern we are only interested in the second record so the main awk block filters for record 2 (NR==2
), printing the first four fields in reverse order, separated by single spaces, with print $4" "$3" "$2" "$1
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论