Как я могу использовать jq для создания CSV с несколькими заголовками и строками? - PullRequest
1 голос
/ 08 февраля 2020

Я хотел бы использовать jq для вывода в формате CSV, но для нескольких заголовков, за которыми следуют несколько деталей. Решения, которые я уже видел в Stack Overflow, предоставляют способ вставить один заголовок, но я не нашел ничего для нескольких заголовков.

Чтобы дать вам представление о том, о чем я говорю, Вот пример JSON input:

[
  {
  "HDR": [1, "abc"],
  "DTL": [ [101,"Descr A"], [102,"Descr B"] ]
  }, {
  "HDR": [2, "def"],
  "DTL": [ [103,"Descr C"], [104,"Descr D"] ]
  }
]

Желаемый результат:

HDR|1|abc
DTL|101|Descr A
DTL|102|Descr B
HDR|2|def
DTL|103|Descr C
DTL|104|Descr D

Я не знаю, возможно ли это, но до сих пор я пытался создать фильтр, чтобы дать мне следующее, поскольку преобразование этого в то, что мне нужно, было бы тривиально:

["HDR", 1, "abc"]
["DTL", 101, "Descr A"]
["DTL", 102, "Descr B"]
["HDR", 2, "def"]
["DTL", 103, "Descr C"]
["DTL", 104, "Descr D"]

Чтобы было ясно, я знаю, как это сделать на любом количестве языков сценариев, но я действительно пытаясь придерживаться одного фильтра JQ, если это вообще возможно.

Редактировать: я должен уточнить, что мне не обязательно копировать ключи "HDR" и "DTL" в CSV (я могу жестко закодировать их), чтобы образец JSON мог выглядеть следующим образом, если это облегчает проблему.

[
  [
    [1, "abc"],
    [[101,"Descr A"], [102,"Descr B"]]
  ], [
    [2, "def"],
    [[103,"Descr C"], [104,"Descr D"]]
  ]
]

Редактировать: Этот фильтр технически отвечает на вопрос вторыми примерами данных, которые я предоставил ( последний, это только массивы и нет объектов), но я все равно был бы признателен за лучший ответ, если бы ни по каким другим причинам, кроме длины заголовка, не нужно было жестко кодировать и помещать HDR в два набора массивов, чтобы его можно было сгладить (), позже я буду чувствовать себя неправильно , Но я оставлю это здесь для справки.

.[] | flatten(1) | [[["HDR"] + .[0:2]]] as $hdr | .[2:] as $dtl | $dtl | map([["DTL"] + .]) as $dtl | $hdr + $dtl | flatten(1) | .[] | join("|")

1 Ответ

2 голосов
/ 08 февраля 2020

Это работает для вашего исходного ввода, если вы выбрали | в качестве разделителя, поскольку ни одно из ваших полей не может содержать |.

jq -r 'map(["HDR"]+.HDR, ["DTL"] + .DTL[])[] | join("|")' data.json
  • map создает несколько элементов массива в object.
  • .DTL[] обеспечивает префикс "DTL" к каждому подсписку
  • [] выравнивает результат map
...