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

我有一些芯片在某些硬件上运行,我想将 shell 命令的输出绑定到一个结构以进行报告/登录。


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

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

试图

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 并绑定到结构或其他东西。


达令说
浏览 114回答 2
2回答

狐的传说

我会将您的输入文件转换为 CSV,因为它适合原始表格数据,也因为 Go 语言在其标准库中有一个 CSV 编码器/解码器:awk -v OFS=',' '&nbsp; &nbsp; $1 == "Num" {&nbsp; &nbsp; &nbsp; &nbsp; count = $3&nbsp; &nbsp; &nbsp; &nbsp; type = $2&nbsp; &nbsp; &nbsp; &nbsp; getline&nbsp; &nbsp; &nbsp; &nbsp; if ( !header++ ) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $(NF+1) = "ID"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; for ( id = 1; id <= count; id++ ) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; getline&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $(NF+1) = type id&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }' file.txt警告:代码不会对字段进行 CSV 转义INDEX,LOAD,MODEL_LOAD,INST,MEM,SHARE_MEM,P2P_MEM,DEVICE,NAMESPACE,ID1,2,3,4,50,600,700,/dev/nvme0,/dev/nvme0n1,decoders:11a,2b,3c,4c,5d,6e,7f,/dev/nvme1,/dev/nvme1n1,decoders:22a,2b,2c,3,0,0,0,/dev/nvme0,/dev/nvme0n1,encoders:11,0,0,0,0,0,0,/dev/nvme1,/dev/nvme1n1,encoders:20,0,0,0,0,0,0,/dev/nvme0,/dev/nvme0n1,scalers:11,0,0,0,0,0,0,/dev/nvme1,/dev/nvme1n1,scalers:2NB在 Go 中为您的输入格式编写解析器应该不会那么困难

慕斯王

如何直接从您关心的 Go 文本开始?与使用 shell 实用程序相比,您在 Go 中拥有更多的控制权。这是一个小型状态机,用于查找前导文本“Num”以指示新项目的开始。下一行是标题,它被跳过,后面的行被转换为一个行,被添加到那个项目。在项目之间的边界和输入文本/文件的末尾,最后一个项目被添加到所有项目的集合中。package mainimport (&nbsp; &nbsp; "bufio"&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "regexp"&nbsp; &nbsp; "strings")var txt = `Num item1: 2INDEX LOAD MODEL_LOAD INST MEM&nbsp; SHARE_MEM P2P_MEM DEVICE&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NAMESPACE1&nbsp; &nbsp; &nbsp;2&nbsp; &nbsp; 3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4&nbsp; &nbsp; 50&nbsp; &nbsp; 600&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;700&nbsp; &nbsp; &nbsp; &nbsp;1&nbsp; &nbsp; &nbsp;11a&nbsp; &nbsp; &nbsp;2b&nbsp; &nbsp; 3c&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4c&nbsp; &nbsp; 5d&nbsp; &nbsp; 6e&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;7f&nbsp; &nbsp; &nbsp; &nbsp;2&nbsp; &nbsp; &nbsp;2Num item2: 2INDEX LOAD MODEL_LOAD INST MEM&nbsp; SHARE_MEM P2P_MEM DEVICE&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NAMESPACE2a&nbsp; &nbsp; &nbsp;2b&nbsp; &nbsp; 2c&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3&nbsp; &nbsp; 0&nbsp; &nbsp; 0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0&nbsp; &nbsp; &nbsp; &nbsp;1&nbsp; &nbsp; &nbsp;11&nbsp; &nbsp; &nbsp;0&nbsp; &nbsp; 0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0&nbsp; &nbsp; 0&nbsp; &nbsp; 0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0&nbsp; &nbsp; &nbsp; &nbsp;2&nbsp; &nbsp; &nbsp;2Num item3: 1INDEX LOAD MODEL_LOAD INST MEM&nbsp; SHARE_MEM P2P_MEM DEVICE&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NAMESPACEi&nbsp; &nbsp; &nbsp;iib&nbsp; &nbsp; iic&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; iii&nbsp; &nbsp; zero&nbsp; &nbsp; zero&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;zero&nbsp; &nbsp; &nbsp; &nbsp;i&nbsp; &nbsp; &nbsp;i**************************************************`var columns = regexp.MustCompile(`\s+`)type Row struct {&nbsp; &nbsp; Index,&nbsp; &nbsp; Load,&nbsp; &nbsp; Model_Load,&nbsp; &nbsp; Inst_Mem,&nbsp; &nbsp; Share_Mem,&nbsp; &nbsp; P2p_Mem,&nbsp; &nbsp; Device,&nbsp; &nbsp; Namespace string}type Item []Rowfunc main() {&nbsp; &nbsp; r := strings.NewReader(txt)&nbsp; &nbsp; scanner := bufio.NewScanner(r)&nbsp; &nbsp; items := make([]Item, 0)&nbsp; &nbsp; var item Item&nbsp; &nbsp; for scanner.Scan() {&nbsp; &nbsp; &nbsp; &nbsp; line := scanner.Text()&nbsp; &nbsp; &nbsp; &nbsp; line = strings.TrimSpace(line)&nbsp; &nbsp; &nbsp; &nbsp; if len(line) == 0 ||&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strings.HasPrefix(line, "***") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; // find beginning of an "item": if any previous item, save it and&nbsp; &nbsp; &nbsp; &nbsp; // reset item to append future rows; skip header line; continue&nbsp; &nbsp; &nbsp; &nbsp; if strings.HasPrefix(line, "Num item") {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if len(item) > 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; items = append(items, item)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; item = make(Item, 0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; scanner.Scan() // skip header&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; cols := columns.Split(line, -1)&nbsp; &nbsp; &nbsp; &nbsp; row := Row{cols[0], cols[1], cols[2], cols[3], cols[4], cols[5], cols[6], cols[7]}&nbsp; &nbsp; &nbsp; &nbsp; item = append(item, row)&nbsp; &nbsp; }&nbsp; &nbsp; // deal with last/trailing item&nbsp; &nbsp; if len(item) > 0 {&nbsp; &nbsp; &nbsp; &nbsp; items = append(items, item)&nbsp; &nbsp; }&nbsp; &nbsp; for i, item := range items {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("Item %d\n", i+1)&nbsp; &nbsp; &nbsp; &nbsp; for _, row := range item {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(row)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}打印以下内容: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}我不知道有什么更好的方法来创建结构,但它是直接的,而且相当干净。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go