使用Golang模板将docker ps输出格式化为JSON

4

我想知道是否可以添加所需的额外格式来使输出成为有效的JSON字符串。为此,我需要在开头添加一个字符,在每一行除了最后一行都添加一个字符,然后在结尾再添加一个字符。

我目前拥有的是这个:

$ sudo docker ps --format "{ \"{{.ID}}\" : \"{{.Names}}\"}"
{ "85c4c597bef9" : "addon_a0d7b954_nodered"}
{ "ec3c55af0497" : "addon_a0d7b954_appdaemon"}
{ "63e3081fbe42" : "addon_a0d7b954_logviewer"}

我不知道如何使用Go语言在开头输出一个单独的字符(甚至不确定是否可能)。


2
请返回已翻译的文本。 - user4466350
看不出它有什么帮助。{{ json .ID }} 只是将该值转换为有效的 JSON,它并没有输出完整的 JSON 字符串(即对象数组)。 - Brian
2
你尝试过 {{json .}} 吗? - user4466350
虽然此命令可以输出有效的JSON格式,但并不完全符合我的要求。与我需要的答案不同,这个版本将所有信息作为有效的JSON字符串给出。该命令如下:echo ] | (sudo docker ps --format "{{json .}}" | paste -sd',' && cat) | (echo [ && cat) - Brian
经过一些尝试,我认为我找到了另一个合适的答案:docker ps -a --format "{{json .}}" | jq "{ID, Names}" | jq -s。 我无法避免调用两次jq,但这很好用。 - user4466350
3个回答

4
问题在于您指定了一个模板,但该模板是在每个容器上单独应用的,每个模板结果都会在新行中呈现。您的模板不适用于项目列表,而是适用于单个项目,输出结果的方式(如何连接行)不在您的控制范围之内。
但是,您可以通过Linux命令实现所需功能。
以下代码演示了如何执行您的模板:
src := "{ \"{{.ID}}\" : \"{{.Names}}\"}"
t := template.Must(template.New("").Parse(src))

ps := []map[string]string{
    {"ID": "85c4c597bef9", "Names": "addon_a0d7b954_nodered"},
    {"ID": "ec3c55af0497", "Names": "addon_a0d7b954_appdaemon"},
    {"ID": "63e3081fbe42", "Names": "addon_a0d7b954_logviewer"},
}

for _, p := range ps {
    if err := t.Execute(os.Stdout, p); err != nil {
        panic(err)
    }
    fmt.Println()
}

这将输出您当前的内容(在Go Playground上试一试)。
{ "85c4c597bef9" : "addon_a0d7b954_nodered"}
{ "ec3c55af0497" : "addon_a0d7b954_appdaemon"}
{ "63e3081fbe42" : "addon_a0d7b954_logviewer"}

您可以使用paste命令将这些行用逗号连接起来,如下所示:

docker ps --format "{ \"{{.ID}}\" : \"{{.Names}}\"}" |paste -sd','

最后一件事:在开头加上[并在结尾加上],这样它就成为一个有效的JSON数组。

要将某些内容附加到命令的输出中,可以使用

echo something | (command && cat)

为了避免echo产生的换行符,您可以使用echo -n

因此,您“期望”的输出是一系列附加项:]附加到docker的输出中,然后再附加到单个[的输出中。

所以,在您的情况下解决方案是:

echo ] | (docker ps --format "{ \"{{.ID}}\" : \"{{.Names}}\"}" | paste -sd',' && cat) | (echo [ && cat)

这将输出:
[
{ "85c4c597bef9" : "addon_a0d7b954_nodered"},{ "ec3c55af0497" : "addon_a0d7b954_appdaemon"},{ "63e3081fbe42" : "addon_a0d7b954_logviewer"}
]

太棒了,非常感谢。我确实使用了之前的建议,使用son格式而不是转义双引号。 - Brian

0

jq 很有帮助。

获取完整的 JSON 以供参考。

docker ps -a --format "{{json .}}" | jq -s

为了在输出中仅获取所需的列,并使用制表符分隔版本

docker ps -a --format "{{json .}}" | jq -r -c '[.ID, .State, .Names, .Image] | @tsv'

0
一个类似 Go 的解决方案可能是这样的,尽管我不确定它在嵌套对象中的行为如何。
package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "os"
)

func main() {
    dec := json.NewDecoder(os.Stdin)
    enc := json.NewEncoder(os.Stdout)
    fmt.Println("[")
    d := map[string]interface{}{}
    var i int
    for {
        err := dec.Decode(&d)
        if err != nil {
            if err == io.EOF {
                break
            }
            log.Println(err)
            continue
        }
        if i > 0 {
            fmt.Println(",")
        }
        enc.Encode(d)
        i++
    }
    fmt.Println("]")
}

然后,docker ps -a --format "{{json .}}" | jq "{ID, Names}" | go run gow/src/test/jsonl/main.go


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接