1264 votes

L'analyse json avec sed et awk

Je suis en train d'essayer de parser json retourné à partir d'une demande curl, comme sp:

curl 'http://twitter.com/users/username.json' | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'

Je l'ai mis en œuvre là où il divise le json dans les champs, c'est à dire la-dessus retours

% ...
"geo_enabled":false
"friends_count":245
"profile_text_color":"000000"
"status":"in_reply_to_screen_name":null
"source":"web"
"truncated":false
"text":"My status"
"favorited":false
% ...

Mais ce que je voudrais faire, c'est prendre un domaine spécifique (indiqué par l'option-v k=texte) et de n'imprimer que.

Des idées?

1700voto

Brian Campbell Points 101107

Je n'ai jamais utilisé, mais vous pouvez essayer jsawk. Il serait quelque chose comme ceci (n'ai pas testé, donc je me trompe peut-être):

curl 'http://twitter.com/users/username.json' | jsawk -a 'return this.name'

331voto

Brendan OConnor Points 2956

Pour extraire rapidement les valeurs pour une touche particulière, personnellement, j'aime utiliser un "grep -o", qui ne renvoie que les regex match. Par exemple, pour obtenir le "champ" texte à partir de tweets, quelque chose comme:

grep -Po '"text":.*?[^\\]",' tweets.json

Cette expression est plus forte que vous le pensez; par exemple, il traite bien avec des chaînes ayant incorporé des virgules et s'est échappé des guillemets à l'intérieur d'eux. Je pense qu'avec un peu plus de travail que vous pourrait faire celui qui est effectivement garantie pour extraire la valeur, si elle est atomique. (Si il y a de nidification, puis une regex ne pouvez pas le faire bien sûr.)

Et à poursuivre l'assainissement (tout en gardant la chaîne d'origine de s'échapper), vous pouvez utiliser quelque chose comme: | perl -pe 's/"text"://; s/^"//; s/",$//'. (Je l'ai fait pour cette analyse.)

Pour tous les rageux qui insistez, vous devez utiliser un vrai parser JSON -- oui, c'est essentiel pour la correction, mais

  1. Pour faire une rapide analyse, comme le comptage de valeurs à vérifier sur le nettoyage des données des bogues ou d'obtenir une idée générale de la données, frapper quelque chose sur la ligne de commande est plus rapide. L'ouverture d'un éditeur pour écrire un script est de distraire.
  2. grep -o est un ordre de grandeur plus rapide que le standard Python json bibliothèque, au moins quand on fait cela pour les tweets (qui sont ~2 KO). Je ne suis pas sûr si c'est juste parce qu' json est lent (je compare à yajl parfois); mais, en principe, d'une expression régulière doit être plus rapide car il est à état fini et bien plus encore optimisable, au lieu d'un analyseur qui a pour support la récursivité, et dans ce cas, passe beaucoup de CPU construisant des arbres pour les structures qui ne vous intéressent pas. (Si quelqu'un a écrit un transducteur à états finis qui n'bon (profondeur limitée) JSON de l'analyse, ce serait fantastique! Dans l'intervalle, nous avons un "grep -o".)

Pour écrire de code faciles à gérer, j'ai toujours l'utilisation d'une analyse de la bibliothèque. Je n'ai pas essayé jsawk, mais si elle fonctionne bien, qui permettrait de régler le point #1.

Une dernière, plus loufoque, la solution: j'ai écrit un script qui utilise Python json et extrait les clés que vous voulez, dans l'onglet séparées par des colonnes; puis je l'ai conduite par un wrapper autour de awk qui permet l'accès nommé à colonnes. Ici: la json2tsv et tsvawk scripts. Donc, pour cet exemple, il serait:

json2tsv id text < tweets.json | tsvawk '{print "tweet " $id " is: " $text}'

Cette approche n'a pas d'adresse #2, est plus inefficace qu'un seul script Python, et c'est un peu fragile: il force la normalisation des retours à la ligne et les tabulations dans les valeurs de chaîne, jouer gentil avec awk sur le terrain/dossier délimité par vision du monde. Mais il ne vous permettre de rester sur la ligne de commande, avec plus d'exactitude qu' grep -o.

195voto

paulkmoore Points 887

Sur la base de ce que certaines des recommandations d'ici esp (dans les commentaires) ont suggéré l'utilisation de Python, j'ai été déçu de ne pas trouver un exemple.

Donc, voici un liner pour obtenir une seule valeur de certaines données JSON. Il suppose que vous êtes la tuyauterie de données (à partir de quelque part) et devrait donc être utile dans un script contexte.

echo '{"hostname":"test","domainname":"example.com"}' | python -c 'import json,sys;obj=json.load(sys.stdin);print obj[0]["hostname"]'

154voto

jnrg Points 724

Suivant MartinR et Boecko plomb :

$ curl -s 'http://twitter.com/users/username.json' | python -mjson.tool

Qui va vous donner une tres grep amicale sortie. Très pratique.

151voto

J.F. Sebastian Points 102961

Vous pouvez simplement télécharger jq binaire pour votre plate-forme et de l'exécuter (chmod +x jq):

$ curl 'https://twitter.com/users/username.json' | ./jq -r '.name'

Extraits d' "name" de l'attribut de l'objet json.

jq page d'accueil dit que c'est comme sed pour les données JSON.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X