Вот решение, которое использует потоковый парсер jq для создания потока, состоящего из $ id1, $ id2 и соответствующего значения интереса;затем этот поток может быть передан в другой инструмент (например, awk, если это удобно) для создания желаемых файлов.
Далее мы используем atomize
из поваренной книги jq:
def atomize(s):
fromstream(foreach s as $in ( {previous:null, emit: null};
if ($in | length == 2) and ($in|.[0][0]) != .previous and .previous != null
then {emit: [[.previous]], previous: $in|.[0][0]}
else { previous: ($in|.[0][0]), emit: null}
end;
(.emit // empty), $in) ) ;
Основная jq-программа (запускаемая с --stream -n -c) будет тогда просто:
atomize(inputs)
| select(type == "object" and .flow)
| .flow
| keys_unsorted[] as $id1
| (.[$id1] | keys_unsorted[]) as $id2
| $id1, $id2, .[$id1][$id2]
Так что для каждого файла gzip, $ gz, конвейер будет выглядеть так:
gunzip -c $ gz |jq -nc --stream -f program.jq |awk ....
Пример использования awk для получения желаемого результата см. в jq, разделении огромного json массива и сохранении в файл с именем со значением
Caveat and Addendum
Потоковый парсер jq избегает использования оперативной памяти за счет скорости, поэтому обычно использование параметра --stream выполняется только в крайнем случае. Из описания проблемы видно, что вы можете обработать некоторые заархивированные файлы с помощью обычного анализатора jq, поэтому вы можете захотеть обработать эти файлы быстро, оставив подход «атомизировать» для тех файлов, которые слишком велики.
Осторожно
В описании проблемы не ясно, что следует делать в случае столкновения id1_id2.json. Если нет возможности такого столкновения, то, конечно, нет проблем. В противном случае это будет зависеть от программы, которая создает эти файлы для управления этим непредвиденным обстоятельством.