为了账号安全,请及时绑定邮箱和手机立即绑定

将 shell 输出绑定到 Go 中的结构的最佳方法?

将 shell 输出绑定到 Go 中的结构的最佳方法?

Go
达令说 2023-02-14 18:15:34
我有一些芯片在某些硬件上运行,我想将 shell 命令的输出绑定到一个结构以进行报告/登录。Num item1: 2INDEX LOAD MODEL_LOAD INST MEM  SHARE_MEM P2P_MEM DEVICE         NAMESPACE1     2    3          4    50    600         700       1     11a     2b    3c          4c    5d    6e         7f       2     2Num item2: 2INDEX LOAD MODEL_LOAD INST MEM  SHARE_MEM P2P_MEM DEVICE         NAMESPACE2a     2b    2c          3    0    0         0       1     11     0    0          0    0    0         0       2     2**************************************************试图cat out.txt | grep -i "Num $1" -A 3 | grep -i nvme | tr -s ' ' | cut -d' ' -f1-7这实际上还不算太糟糕,我可以传入一个 argdecoders或encoders并获取每个芯片的负载指标。但是,我现在很好奇将它绑定到 Go 中的结构的最佳方法。目前,我能做的是编写一个自定义解串器,例如:func main() {    out, err := exec.Command("/bin/sh", "metrics.sh", "encoders").Output()    if err != nil {        fmt.Println(err)        log.Fatal(err)    }    fmt.Println(string(out))}但我觉得必须有更好的方法,比如输出为 JSON 并绑定到结构或其他东西。
查看完整描述

2 回答

?
狐的传说

TA贡献1804条经验 获得超3个赞

我会将您的输入文件转换为 CSV,因为它适合原始表格数据,也因为 Go 语言在其标准库中有一个 CSV 编码器/解码器:


awk -v OFS=',' '

    $1 == "Num" {

        count = $3

        type = $2


        getline

        if ( !header++ ) {

            $(NF+1) = "ID"

            print

        }

        for ( id = 1; id <= count; id++ ) {

            getline

            $(NF+1) = type id

            print

        }

    }

' file.txt

警告:代码不会对字段进行 CSV 转义


INDEX,LOAD,MODEL_LOAD,INST,MEM,SHARE_MEM,P2P_MEM,DEVICE,NAMESPACE,ID

1,2,3,4,50,600,700,/dev/nvme0,/dev/nvme0n1,decoders:1

1a,2b,3c,4c,5d,6e,7f,/dev/nvme1,/dev/nvme1n1,decoders:2

2a,2b,2c,3,0,0,0,/dev/nvme0,/dev/nvme0n1,encoders:1

1,0,0,0,0,0,0,/dev/nvme1,/dev/nvme1n1,encoders:2

0,0,0,0,0,0,0,/dev/nvme0,/dev/nvme0n1,scalers:1

1,0,0,0,0,0,0,/dev/nvme1,/dev/nvme1n1,scalers:2

NB在 Go 中为您的输入格式编写解析器应该不会那么困难


查看完整回答
反对 回复 2023-02-14
?
慕斯王

TA贡献1864条经验 获得超2个赞

如何直接从您关心的 Go 文本开始?与使用 shell 实用程序相比,您在 Go 中拥有更多的控制权。


这是一个小型状态机,用于查找前导文本“Num”以指示新项目的开始。下一行是标题,它被跳过,后面的行被转换为一个行,被添加到那个项目。在项目之间的边界和输入文本/文件的末尾,最后一个项目被添加到所有项目的集合中。


package main


import (

    "bufio"

    "fmt"

    "regexp"

    "strings"

)


var txt = `

Num item1: 2

INDEX LOAD MODEL_LOAD INST MEM  SHARE_MEM P2P_MEM DEVICE         NAMESPACE

1     2    3          4    50    600         700       1     1

1a     2b    3c          4c    5d    6e         7f       2     2

Num item2: 2

INDEX LOAD MODEL_LOAD INST MEM  SHARE_MEM P2P_MEM DEVICE         NAMESPACE

2a     2b    2c          3    0    0         0       1     1

1     0    0          0    0    0         0       2     2

Num item3: 1

INDEX LOAD MODEL_LOAD INST MEM  SHARE_MEM P2P_MEM DEVICE         NAMESPACE

i     iib    iic          iii    zero    zero         zero       i     i

**************************************************

`


var columns = regexp.MustCompile(`\s+`)


type Row struct {

    Index,

    Load,

    Model_Load,

    Inst_Mem,

    Share_Mem,

    P2p_Mem,

    Device,

    Namespace string

}


type Item []Row


func main() {

    r := strings.NewReader(txt)

    scanner := bufio.NewScanner(r)


    items := make([]Item, 0)


    var item Item

    for scanner.Scan() {

        line := scanner.Text()

        line = strings.TrimSpace(line)


        if len(line) == 0 ||

            strings.HasPrefix(line, "***") {

            continue

        }


        // find beginning of an "item": if any previous item, save it and

        // reset item to append future rows; skip header line; continue

        if strings.HasPrefix(line, "Num item") {

            if len(item) > 0 {

                items = append(items, item)

                item = make(Item, 0)

            }

            scanner.Scan() // skip header

            continue

        }


        cols := columns.Split(line, -1)

        row := Row{cols[0], cols[1], cols[2], cols[3], cols[4], cols[5], cols[6], cols[7]}

        item = append(item, row)

    }


    // deal with last/trailing item

    if len(item) > 0 {

        items = append(items, item)

    }


    for i, item := range items {

        fmt.Printf("Item %d\n", i+1)

        for _, row := range item {

            fmt.Println(row)

        }

    }

}

打印以下内容:


Item 1

{1 2 3 4 50 600 700 1}

{1a 2b 3c 4c 5d 6e 7f 2}

Item 2

{2a 2b 2c 3 0 0 0 1}

{1 0 0 0 0 0 0 2}

Item 3

{i iib iic iii zero zero zero i}

我不知道有什么更好的方法来创建结构,但它是直接的,而且相当干净。


查看完整回答
反对 回复 2023-02-14
  • 2 回答
  • 0 关注
  • 113 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信