Lire les données json dans le script shell

En shell, je dois lire la réponse JSON au format suivant:

{ "Messages": [ { "Body": "172.16.1.42|/home/480/1234/5-12-2013/1234.toSort", "ReceiptHandle": "uUk89DYFzt1VAHtMW2iz0VSiDcGHY+H6WtTgcTSgBiFbpFUg5lythf+wQdWluzCoBziie8BiS2GFQVoRjQQfOx3R5jUASxDz7SmoCI5bNPJkWqU8ola+OYBIYNuCP1fYweKl1BOFUF+o2g7xLSIEkrdvLDAhYvHzfPb4QNgOSuN1JGG1GcZehvW3Q/9jq3vjYVIFz3Ho7blCUuWYhGFrpsBn5HWoRYE5VF5Bxc/zO6dPT0n4wRAd3hUEqF3WWeTMlWyTJp1KoMyX7Z8IXH4hKURGjdBQ0PwlSDF2cBYkBUA=", "MD5OfBody": "53e90dc3fa8afa3452c671080569642e", "MessageId": "e93e9238-f9f8-4bf4-bf5b-9a0cae8a0ebc" } ] } 

Ici, je ne suis concerné que par la valeur de la propriété “Body”. J’ai fait quelques tentatives infructueuses comme:

  jsawk -a 'return this.Body' 

ou

  awk -vk="Body" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]} 

Mais cela ne suffisait pas. Est-ce que quelqu’un peut m’aider avec ça?

Il y a jq pour parsingr json sur la ligne de commande:

  jq '.Body' 

Visitez ceci pour jq: https://stedolan.github.io/jq/

tl; dr

 $ cat /tmp/so.json | underscore select '.Messages .Body' ["172.16.1.42|/home/480/1234/5-12-2013/1234.toSort"] 

Les outils Javascript de la CLI

Vous pouvez utiliser des outils Javascript de la CLI comme

  • souligné-cli :
  • json: select () : sélecteurs de type CSS pour JSON.

Exemple

Sélectionnez tous les name enfants d’un addons :

 underscore select ".addons > .name" 

Le underscore-cli fournit d’autres exemples réels ainsi que le json: select () doc .

De même en utilisant Bash regexp. Doit pouvoir arracher n’importe quelle paire clé / valeur.

 key="Body" re="\"($key)\": \"([^\"]*)\"" while read -rl; do if [[ $l =~ $re ]]; then name="${BASH_REMATCH[1]}" value="${BASH_REMATCH[2]}" echo "$name=$value" else echo "No match" fi done 

Les expressions régulières peuvent être ajustées pour correspondre à plusieurs espaces / tabulations ou nouvelles lignes. Ne fonctionnerait pas si la valeur était intégrée " . Ceci est une illustration. Mieux vaut utiliser un parsingur” indussortingel “:)

Voici un moyen simple de le faire: Transformez JSON en variables bash pour les eval .

Cela ne fonctionne que pour:

  • JSON qui ne contient pas de tableaux nesteds, et
  • JSON provenant de sources dignes de confiance (sinon cela peut perturber votre script shell, peut-être même peut-être endommager votre système, vous avez été prévenu )

Eh bien, oui, il utilise PERL pour faire ce travail, grâce à CPAN, mais il est assez petit pour être inclus directement dans un script et est donc rapide et facile à déboguer:

 json2bash() { perl -MJSON -0777 -n -E 'sub J { my ($p,$v) = @_; my $r = ref $v; if ($r eq "HASH") { J("${p}_$_", $v->{$_}) for keys %$v; } elsif ($r eq "ARRAY") { $n = 0; J("$p"."[".$n++."]", $_) foreach @$v; } else { $v =~ '"s/'/'\\\\''/g"'; $p =~ s/^([^[]*)\[([0-9]*)\](.+)$/$1$3\[$2\]/; $p =~ tr/-/_/; $p =~ tr/A-Za-z0-9_[]//cd; say "$p='\''$v'\'';"; } }; J("json", decode_json($_));' } 

utilisez-le comme eval "$(json2bash <<<'{"a":["b","c"]}')"

Pas lourdement testé, cependant. Mises à jour, avertissements et autres exemples voir mon GIST .

Mettre à jour

(Malheureusement, la suite est une solution de lien uniquement, car le code C est beaucoup trop long pour être dupliqué ici.)

Pour tous ceux qui n'aiment pas la solution ci-dessus, il y a maintenant un programme C json2sh qui (espérons-le, en toute sécurité) convertit JSON en variables shell. Contrairement à l'extrait de code perl , il est capable de traiter n'importe quel JSON, à condition qu'il soit bien formé.

Mises en garde:

  • json2sh n'a pas été beaucoup testé.
  • json2sh peut créer des variables qui commencent par le motif shellshock () {

J'ai écrit json2sh pour pouvoir post-traiter .bson avec Shell:

 bson2json() { printf '['; { bsondump "$1"; echo "\"END$?\""; } | sed '/^{/s/$/,/'; echo ']'; }; bsons2json() { printf '{'; c=''; for a; do printf '%s"%q":' "$c" "$a"; c=','; bson2json "$a"; done; echo '}'; }; bsons2json */*.bson | json2sh | .. 

Expliqué:

  • bson2json un fichier .bson tel que les enregistrements deviennent un tableau JSON
    • Si tout fonctionne correctement, un END0 END0 est appliqué, sinon vous verrez quelque chose comme END1 .
    • Le END -Marker est nécessaire, sinon les fichiers .bson vides ne seront pas affichés.
  • bsons2json un tas de fichiers .bson en tant qu'object, où la sortie de bson2json est indexée par le nom du fichier.

Ceci est alors post- json2sh par json2sh , de sorte que vous pouvez utiliser grep / source / eval / etc. ce que vous avez besoin, pour amener les valeurs dans la coquille.

De cette façon, vous pouvez rapidement traiter le contenu d'un cliché MongoDB au niveau du shell, sans avoir à l'importer dans MongoDB.