группировать вывод json по входному значению массива - PullRequest
1 голос
/ 25 сентября 2019

Входные данные: /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 '[input |./ "\ n" |. [] / "\ t" | select (длина> 0) |.как $ input | (если $ input [0] == «INPUT», то $ input [1] else {($ input [0]): $ input [1]} end)] '/tmp/h1.tabs

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

Я пробовал такие выражения, как если бы $ input [0] == "INPUT", а затем $ block = $ input [1], но мне не повезло с назначением, поэтому я не могуиспользуйте назначение в выводе.На самом деле, мне кажется, мне нужна переменная, для которой устанавливается значение INPUT каждый раз, когда я его передаю.Затем я могу отформатировать вывод по мере необходимости.Мне просто не хватает ключевой магии.Я долго к этому стучал, вот еще что не работает ...

# 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

Все еще учусь: -)

Ответы [ 2 ]

2 голосов
/ 25 сентября 2019

reduce ваш друг ..

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

Обратите внимание, что вам нужно указать опции -n и -R в командной строке, чтобы это работало

1 голос
/ 26 сентября 2019

Использование 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 Assisted):

{
  "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"
  }
}
...