У меня есть JSON, содержащий массив объектов, каждый объект содержит уникальное значение в:
"id":"value"
Я следовал этому и я могу разделить весь документ на несколько файлов, используя jq и awk
jq -c ".[]" big.json | gawk '{print > "doc00" NR ".json";}'
таким образом, выходные файлы именуются последовательно.
Как я могу назвать файлы, используя значение id
?
Всего 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))
Обработка разбиения может быть выполнена, как описано в другом месте на этой странице.