从 Bash 脚本中的 Dmidecode 输出中获取特定数值

huangapple go评论62阅读模式
英文:

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 &#39;BEGIN{RS=&quot;01[[:space:]]85[[:space:]]30&quot;}NR&gt;1{print $4 $3 $2 $1}&#39;

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 &#39;BEGIN{ORS=&quot; &quot;; OFS=&quot; &quot;} {gsub(FS,&quot; &quot;,$0); $1=$1; print$0}&#39; file | awk -v pattern=&quot;01 85 30&quot; &#39;BEGIN{RS=pattern} NR==2{print $4&quot; &quot;$3&quot; &quot;$2&quot; &quot;$1}&#39;

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 &#39;BEGIN{ORS=&quot; &quot;; OFS=&quot; &quot;} {gsub(FS,&quot; &quot;,$0); $1=$1; print$0}&#39; 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,&quot; &quot;,$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=&quot;01 85 30&quot; &#39;BEGIN{RS=pattern} NR==2{print $4&quot; &quot;$3&quot; &quot;$2&quot; &quot;$1}&#39;

uses the variable flag v to pass the search pattern into the awk procedure -v pattern=&quot;01 85 30&quot; 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&quot; &quot;$3&quot; &quot;$2&quot; &quot;$1

huangapple
  • 本文由 发表于 2023年2月18日 19:44:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/75493097.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定