web-dev-qa-db-fra.com

Lire des données JSON dans un script Shell

Dans Shell, je suis obligé de 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 des tentatives infructueuses comme:

 jsawk -a 'return this.Body' 

ou

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

Mais cela n'a pas suffi. Est-ce que quelqu'un peut m'aider avec ça?

50
user1305398

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

 jq '.Body'

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

80
user1305398

tl; dr

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

Outils CLI Javascript

Vous pouvez utiliser des outils CLI Javascript tels que

Exemple

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

underscore select ".addons > .name"

Le underscore-cli fournit d'autres exemples du monde réel ainsi que le json: select () doc .

12
Édouard Lopez

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

key="Body"
re="\"($key)\": \"([^\"]*)\""

while read -r l; do
    if [[ $l =~ $re ]]; then
        name="${BASH_REMATCH[1]}"
        value="${BASH_REMATCH[2]}"
        echo "$name=$value"
    else
        echo "No match"
    fi
done

L'expression régulière peut être ajustée pour correspondre à plusieurs espaces/onglets ou nouvelle (s) ligne (s). Ne fonctionnerait pas si la valeur avait incorporé ". Ceci est une illustration. Mieux vaut utiliser un analyseur "industriel" :)

5
Mindaugas Kubilius

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

Cela ne fonctionne que pour:

  • JSON qui ne contient pas de tableaux imbriqués, et
  • JSON provenant de sources fiables (sinon, cela pourrait perturber votre script Shell, voire même endommager votre système, Vous avez été averti )

Eh bien, oui, il utilise Perl pour effectuer ce travail, grâce à CPAN, mais il est suffisamment 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 .

Mise à jour

(Malheureusement, la solution suivante est un 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 existe maintenant un programme C json2sh qui (espérons-le en toute sécurité) convertit JSON en variables Shell. Contrairement à l'extrait Perl, il est capable de traiter n'importe quel fichier JSON, tant qu'il est 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 | ..

A expliqué:

  • bson2json sauvegarde un fichier .bson de sorte que les enregistrements deviennent un tableau JSON
    • Si tout fonctionne correctement, un marqueur END0- est appliqué. Sinon, vous verrez quelque chose comme END1.
    • Le marqueur END- est nécessaire, sinon les fichiers .bson vides ne s'afficheraient pas.
  • bsons2json dump un tas de fichiers .bson sous forme d'objet, où la sortie de bson2json est indexée par le nom du fichier.

Ceci est ensuite traité par json2sh, de sorte que vous pouvez utiliser grep/source/eval/etc. ce dont vous avez besoin pour apporter les valeurs dans Shell.

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

1
Tino