У меня есть документ JSON ниже для преобразования в CSV. Мне нужно перебрать первый столбец со вторым и третьим (они могут быть строкой или массивом) одновременно с одной итерацией.

Пример документа:

[
  {
    "results": [
       [
        "abc025",
        "true",
        "test.lun"
      ],
       [
        "xyz025",
        [
          "true",
          "false",
          "true"
        ],
        [
          "product.lun",
          "app.lun",
          "ora.lun"
        ]
      ]
    ]
  }
]

Ожидаемый CSV:

"abc025","true","test.lun"
"xyz025","true","product.lun"
"xyz025","false","app.lun"
"xyz025","true","ora.lun"
1
Kusalananda 23 Авг 2021 в 11:15
Конечно, у этого есть более 1 массива, также я хотел бы узнать, как перебирать первую строку со 2-м и 3-м массивами с одним и тем же индексом, ожидаемый результат показывает логику, отличную от последней. Благодарность
 – 
Henry Liu
23 Авг 2021 в 07:51
Действительно ли значения в массиве xyz025 не заключены в кавычки, и вы хотите, чтобы они были заключены в кавычки? Существует большая разница между false (логическим значением) и "false" (строкой) в JSON.
 – 
Kusalananda
23 Авг 2021 в 09:13
Да я отредактирую пост
 – 
Henry Liu
23 Авг 2021 в 09:30
Это самое большее, что я мог сделать, но xyz025 отсутствует во 2-м и 3-м рядах. '.[].результаты[] | [ [ .[0][]? // .[0] ], [ .[1][]? // .[1] ], [ .[2][]? // .[2] ] ] | to_entries | (карта (.value) | транспонировать []) | @csv'
 – 
Henry Liu
23 Авг 2021 в 09:37
Спасибо за обновление, пожалуйста, также отредактируйте свой вопрос, чтобы добавить свой ответ в комментарии в основную часть вопроса, который у вас есть,
 – 
αғsнιη
23 Авг 2021 в 12:58

1 ответ

Лучший ответ

Используйте выражение jq

.[].results[] | .[0] as $name | .[1:] | map([.[]]? // [.]) |
(.[0]|keys[]) as $i | [ $name, .[][$i] ] | @csv

Первая строка здесь выбирает $name в качестве первого элемента (.[0]) из каждого отдельного подмассива (abc025 и xyz025 соответственно, в отдельных итерациях), а затем преобразует оставшиеся данные в каждом подмассиве (.[1:]) в массивы по одному массиву на столбец:

[["true"],["test.lun"]]
[["true","false","true"],["product.lun","app.lun","ora.lun"]]

Это делается в вызове map(), где каждый элемент извлекается как массив. Если это не работает, элемент помещается в массив. Таким образом, каждый элемент либо остается массивом, либо преобразуется в массив из одного элемента.

Вторая строка перебирает индексы этих массивов столбцов и создает выходные данные в виде CSV.

Тестирование:

$ jq -r '.[].results[] | .[0] as $name | .[1:] | map([.[]]? // [.]) | (.[0]|keys[]) as $i | [ $name, .[][$i] ] | @csv' file
"abc025","true","test.lun"
"xyz025","true","product.lun"
"xyz025","false","app.lun"
"xyz025","true","ora.lun"

Обратите внимание, что это обобщение моего решения вашего предыдущего вопроса. Вы также можете использовать этот код со своими данными из этого вопроса.

Вы также можете использовать это для данных с более чем тремя столбцами. Документ

[
  {
    "results": [
      [ "abc025",
        "true",
        "test.lun",
        "blueberry" ],
      [ "xyz025",
        ["true","false","true"],
        ["product.lun","app.lun","ora.lun"],
        ["strawberry","cloudberry","lingonberry"] ]
    ]
  }
]

Превратится в

"abc025","true","test.lun","blueberry"
"xyz025","true","product.lun","strawberry"
"xyz025","false","app.lun","cloudberry"
"xyz025","true","ora.lun","lingonberry"
2
Kusalananda 23 Авг 2021 в 12:35
1
Большое спасибо @Kusalananda, вы действительно очень помогли мне в изучении этого нового инструмента.
 – 
Henry Liu
23 Авг 2021 в 10:32