Вопрос показывает поток объектов JSON, поэтому следующие решения предполагают, что входной файл уже является последовательностью, как показано. Эти решения также могут быть легко адаптированы для случая, когда входной файл содержит огромный массив объектов, например, как обсуждено в эпилоге.
Решение с двумя вызовами
Вот двухпроходное решение, использующее два вызова jq. Презентация предполагает среду, похожую на bash, на случай, если у вас wsl :
n=$(jq -n 'reduce (inputs|.labels|length) as $i (-1;
if $i > . then $i else . end)' stream.json)
jq -nr --argjson n $n '
def fill($n): . + [range(length;$n)|null];
[range(0;$n)|"labels"],
(inputs | .labels | fill($n))
| @csv' stream.json
Предполагая, что ввод такой, как описано, это гарантирует получение действительного CSV. Надеемся, что вы можете адаптировать вышесказанное к вашей оболочке по мере необходимости - возможно, эта ссылка поможет
Назначить вывод программы переменной с помощью командного файла MS
Использование input_filename
и один вызов jq
К сожалению, у jq нет функции "перемотки", но
есть альтернатива: прочитать файл дважды за один вызов jq. Это более громоздко, чем приведенное выше решение с двумя вызовами, но позволяет избежать любых трудностей, связанных с последним.
cat sample.json | jq -nr '
def fill($n): . + [range(length;$n)|null];
def max($x): if . < $x then $x else . end;
foreach (inputs|.labels) as $in ( {n:0};
if input_filename == "<stdin>"
then .n |= max($in|length)
else .printed+=1
end;
if .printed == null then empty
else .n as $n
| (if .printed == 1 then [range(0;$n)|"labels"] else empty end),
($in | fill($n))
end)
| @csv' - sample.json
Еще одно решение с одним вызовом
Следующее решение использует специальное значение (здесь null
) для разграничения двух потоков:
(cat stream.json; echo null; cat stream.json) | jq -nr '
def fill($n): . + [range(length; $n) | null];
def max($x): if . < $x then $x else . end;
(label $loop | foreach inputs as $in (0;
if $in == null then . else max($in|.labels|length) end;
if $in == null then ., break $loop else empty end)) as $n
| [range(0;$n)|"labels"],
(inputs | .labels | fill($n))
| @csv '
Эпилог
Файл с массивом JSON верхнего уровня, который слишком велик для размещения в памяти, можно преобразовать в поток элементов массива, вызвав jq с параметром --stream, например, следующим образом:
jq -cn --stream 'fromstream(1|truncate_stream(inputs))'