【问题标题】:group json output by array input value按数组输入值分组 json 输出
【发布时间】:2019-09-25 14:27:05
【问题描述】:

输入数据:/tmp/h1.tabs,制表符分隔:

INPUT   A1
Flavor  Controller
Comment Disabled
State   DiskOne
INPUT   B2
Flavor  Controller
Comment Not Applicable
State   Not Applicable
ConnectorCount  12
Alarm   Alarm Not present
INPUT   C3
Flavor  Controller
Comment Not Applicable
Media   Not Applicable
ConnectorCount  0
State   Alarm Not present

期望的输出:

{
    "A1": {
        "Comment": "Disabled",
        "Flavor": "Controller",
        "State": "DiskOne"
    },
    "B2": {
        "Alarm": "Alarm Not present",
        "Comment": "Not Applicable",
        "ConnectorCount": "12",
        "Flavor": "Controller",
        "State": "Not Applicable"
    },
    "C3": {
        "Comment": "Not Applicable",
        "ConnectorCount": "0",
        "Flavor": "Controller",
        "Media": "Not Applicable",
        "State": "Alarm Not present"
    }
}

每个 INPUT 字典键也可以是一个数组而不是另一个字典。

{
    "A1": [
        { "Comment": "Disabled" },
        { "Flavor": "Controller" },
        { "State": "DiskOne" }
    ],

我能做到的大概是这样的:

jq -Rsn '[输入|。 / "\n"|.[] / "\t"|选择(长度 > 0)|. as $input|(if $input[0] == "INPUT" then $input[1] else { ($input[0]): $input[1] } end)]' /tmp/h1.tabs

[
  "A1",
  {
    "Flavor": "Controller"
  },
  {
    "Comment": "Disabled"
  },
  {
    "State": "DiskOne"
  },
  "B2",
  {
    "Flavor": "Controller"
  },

我已经尝试过 if $input[0] == "INPUT" then $block = $input[1] 这样的表达式,但我的赋值没有任何运气,所以我不能在输出。真的,我认为我需要的是一个变量,每次传递它时都设置为任何 INPUTs 值。然后我可以根据需要格式化输出。我只是缺少一些关键的魔法。我已经敲了一段时间了,这里还有更多不起作用...

# vim:ft=ansible:tabstop=8 expandtab shiftwidth=2 softtabstop=2
"unknown" as $block
|[
  inputs
  |. / "\n"
  |
  (
    .[]
    | select(length > 0)
    |.
  )
]
|(.[] / "\t")
|select(length > 0)
|. as $input
|
(
  if $input[0] == "INPUT" then $block = $input[1] else empty end
  |({($block): [($input[0]):($input[1])]})
) | add

还在学习中:-)

【问题讨论】:

    标签: json jq


    【解决方案1】:

    reduce 是你的朋友..

    reduce (inputs / "\t") as [$k, $v] ([];
        if $k == "INPUT" then
            .[0] = $v
        else
            .[1][.[0]] += {($k): $v}
        end
    ) | .[1]
    

    请注意,您需要在命令行中指定 -n 和 -R 选项才能正常工作

    【讨论】:

    • 我将不得不考虑一段时间。效果很好。我喜欢 k,v 的编辑,更干净。 .[0]、.[1] 是什么?只是任意索引变量?我理解这里的任务......当我试图将它们“内联”时,我无法让它工作......我猜是错误的地方。谢谢。
    • 是的,我猜他们就是这么称呼的。它将 A1、B2 等保存在 .[0] 中以供参考,并在 .[1] 中构建所需的对象
    【解决方案2】:

    使用 GNU awk、gawkextlib 和 gawk-json:

    $ gawk '
    @load "json"
    BEGIN{
        FS="\t"
    }
    {
        if($1=="INPUT")
            tl=$2
        else
            data[tl][$1]=$2
    }
    END {
        print json_toJSON(data)
    }' file                           # | jq '.'  # for eye-friendly formating
    

    输出(jq 协助):

    {
      "C3": {
        "Comment": "Not Applicable",
        "State": "Alarm Not present",
        "ConnectorCount": "0",
        "Flavor": "Controller",
        "Media": "Not Applicable"
      },
      "A1": {
        "Comment": "Disabled",
        "State": "DiskOne",
        "Flavor": "Controller"
      },
      "B2": {
        "Comment": "Not Applicable",
        "State": "Not Applicable",
        "Alarm": "Alarm Not present",
        "ConnectorCount": "12",
        "Flavor": "Controller"
      }
    }
    

    【讨论】:

    • 不错。我必须承认,这种方法对我的编程大脑来说更舒服。我还没有克服 jq 的学习曲线(还)
    • @Greg 我知道。请参阅我的评论here。
    猜你喜欢
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-12
    相关资源
    最近更新 更多