JQ, разделить огромный JSON массива и сохранить в файл с именем со значением

Всего 3 ответа


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

jq -cr '.[] | .id, .' big.json | awk 'NR%2{f=$0".json";next} {print >f;close(f)}'

Использование .id как части имени файла чревато риском.

Во-первых, существует потенциальная проблема встроенных символов новой строки.

Во-вторых, существует проблема «зарезервированных» символов, особенно «/».

В-третьих, Windows имеет многочисленные ограничения на имена файлов - см., Например, https://gist.github.com/doctaphred/d01d05291546186941e1b7ddc02034d3 ).

Кроме того, если используется опция -r в jq, как предложено в другой публикации на этой странице, то значения .id, равные "1" и 1 будут сопоставлены с 1 , что приведет к потере данных, если «>» используется в AWK.

Итак, вот решение, которое иллюстрирует, как безопасность может быть достигнута в среде OS X или * ix, и это имеет большое значение для безопасного решения для Windows:

jq -c '.[]
       | (.id | if type == "number" then .
                else tostring | gsub("[^A-Za-z0-9-_]";"+") end), .' |
awk '
  function fn(s) { sub(/^"/,"",s); sub(/"$/,"",s); return s ".json"; }
  NR%2{f=fn($0); next} 
  {print >> f; close(f);}
' 

Обратите особое внимание на использование «>>», чтобы избежать потери данных в случае конфликтов имен файлов.


Поскольку в описании проблемы указано, что входной массив огромен, возможно, стоит подумать об использовании потокового парсера jq. В целом, это было бы целесообразно, если входной JSON слишком велик для чтения в память или если важной целью является снижение требований к памяти компьютера.

Вкратце, вместо обычного вызова jq добавляются параметры командной строки -n и --stream и заменяется начальный .[] :

fromstream(1|truncate_stream(inputs))

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


Есть идеи?

10000