1
votes

jq, divisez un énorme json de tableau et enregistrez-le dans un fichier nommé avec une valeur

J'ai un json contenant un tableau d'objets, chaque objet contient une valeur unique dans:

jq -c ".[]" big.json | gawk '{print > "doc00" NR ".json";}'

j'ai suivi ceci autre réponse et je peux diviser le document entier en plusieurs fichiers en utilisant jq et awk

"id":"value"

de cette façon, les fichiers de sortie sont nommés séquentiellement.
comment puis-je nommer les fichiers en utilisant la valeur id ?


0 commentaires

3 Réponses :


2
votes

Pour chaque élément du tableau, affichez l'identifiant et l'élément lui-même sur deux lignes distinctes, vous pouvez ainsi récupérer l'identifiant des lignes impaires et imprimer les lignes paires dans les fichiers nommés avec l'identifiant.

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


5 commentaires

L'OP n'a pas utilisé l'option de ligne de commande -r, et son utilisation comporte un risque potentiel (lié aux chaînes avec des caractères de nouvelle ligne incorporés) qui devrait être mentionné. Si l’on sait que les entités JSON imprimées ne sont pas des chaînes JSON, alors l’utilisation de -r est inutile. Dans l’ensemble, il serait donc préférable de l’omettre à moins qu’il ne puisse être établi que cela est vraiment nécessaire.


@peak Oui, vous avez un point, mais si nous supprimons -r, nous devrions supprimer les guillemets doubles dans le script awk, ce qui ne me semble pas une bonne idée: /


Et si l'élément du tableau a une clé, il est garanti qu'il s'agit d'un objet, et -r ne le changera pas, non?


Oui, mais dans le cas particulier décrit par l'OP, le risque est que le .id contienne une nouvelle ligne.


oh oui, ce serait une déception



1
votes

L'utilisation de .id comme partie d'un nom de fichier comporte de nombreux risques.

Premièrement, il y a le problème potentiel des caractères de retour à la ligne incorporés.

Deuxièmement, il y a le problème des caractères "réservés", notamment "/".

Troisièmement, Windows a de nombreuses restrictions sur les noms de fichiers - voir par exemple https://gist.github.com/doctaphred/d01d05291546186941e1b7ddc0).

p> De plus, si l'option -r de jq est utilisée, comme suggéré dans une autre publication sur cette page, alors les valeurs .id de "1" et 1 seront toutes les deux mappées à 1 , ce qui entraînera une perte de données si ">" est utilisé dans awk.

Voici donc une solution qui illustre comment la sécurité peut être obtenue dans un OS X ou * ix et cela va un long chemin vers une solution sûre pour 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);}
' 

Notez en particulier l'utilisation de ">>" pour éviter de perdre des données en cas de conflits de noms de fichiers .


0 commentaires

0
votes

Puisque la description du problème indique que le tableau d'entrée est énorme, il peut être intéressant d'envisager d'utiliser l'analyseur de flux de jq. En général, cela conviendrait si l'entrée JSON est trop grande pour être lue en mémoire, ou si la réduction des besoins en mémoire de l'ordinateur est un objectif important.

En bref, au lieu d'appeler jq de manière normale, on ajoute le -n et les options de ligne de commande --stream, et remplace le . [] initial par:

fromstream(1|truncate_stream(inputs))

La gestion du fractionnement peut alors être effectuée comme décrit ailleurs sur cette page.


0 commentaires