Parsing JSON avec des outils Unix

j'essaie de parser les retours de JSON d'une requête curl, comme ça:

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

ce qui précède divise le JSON en champs, par exemple:

% ...
"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
% ...

comment imprimer un champ spécifique (indiqué par le -v k=text )?

577
demandé sur codeforester 2009-12-24 00:46:58

30 réponses

il existe un certain nombre d'outils spécialement conçus pour manipuler JSON à partir de la ligne de commande, et sera beaucoup plus facile et plus fiable que de le faire avec Awk, comme: jq :

curl -s 'https://api.github.com/users/lambda' | jq -r '.name'

vous pouvez également le faire avec des outils qui sont probablement déjà installés sur votre système, comme Python en utilisant le json module , et donc éviter toute dépendance supplémentaire, tout en ayant toujours le avantage d'un bon analyseur JSON. Les hypothèses suivantes que vous voulez utiliser UTF-8, dans lequel le JSON original devrait être encodé et est ce que la plupart des terminaux modernes utilisent aussi bien:

Python 2:

export PYTHONIOENCODING=utf8
curl -s 'https://api.github.com/users/lambda' | \
    python -c "import sys, json; print json.load(sys.stdin)['name']"

Python 3:

curl -s 'https://api.github.com/users/lambda' | \
    python3 -c "import sys, json; print(json.load(sys.stdin)['name'])"

notes historiques

Cette réponse initialement recommandé jsawk , qui doit encore fonctionner, mais est un peu plus compliqué à utiliser que jq , et dépend de l'installation d'un interpréteur JavaScript autonome moins courant qu'un interpréteur Python, de sorte que les réponses ci-dessus sont probablement préférables:

curl -s 'https://api.github.com/users/lambda' | jsawk -a 'return this.name'

cette réponse a aussi utilisé à l'origine L'API Twitter de la question, mais cette API ne fonctionne plus, ce qui rend difficile de copier les exemples à tester, et la nouvelle API Twitter nécessite des clés API, donc je suis passé à l'aide de L'API GitHub qui peut être utilisé facilement sans clés API. Le la première réponse à la question initiale:

curl 'http://twitter.com/users/username.json' | jq -r '.text'
671
répondu Brian Campbell 2016-09-09 18:06:18

pour extraire rapidement les valeurs d'une clé particulière, j'aime personnellement utiliser" grep-o", qui ne renvoie que la correspondance regex. Par exemple, pour obtenir le champ" text "des tweets, quelque chose comme:

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

ce regex est plus robuste que vous pourriez le penser; par exemple, il traite bien avec des chaînes ayant des virgules intégrées et des citations échappées à l'intérieur d'eux. Je pense qu'avec un peu plus de travail vous pourriez en faire un qui est en fait garanti pour extraire la valeur, si c'est atomique. (Si elle a la nidification, alors un regex ne peut pas le faire bien sûr.)

et pour nettoyer davantage (tout en gardant l'original de la corde échapper) vous pouvez utiliser quelque chose comme: | perl -pe 's/"text"://; s/^"//; s/",$//' . (J'ai fait cela pour cette analyse .)

à tous les ennemis qui insistent pour que vous utilisiez un vrai JSON parser -- Oui, c'est essentiel pour l'exactitude, mais

  1. pour faire une analyse très rapide, comme Compter valeurs pour vérifier les bugs de nettoyage de données ou obtenir une impression générale pour les données, frapper quelque chose sur la ligne de commande est plus rapide. Ouvrir un éditeur pour écrire un script est distrayant.
  2. grep -o est des ordres de grandeur plus rapides que la bibliothèque standard de Python json , au moins quand on fait cela pour les tweets (qui sont ~2 KB chacun). Je ne suis pas sûr si c'est juste parce que json est lent (je devrais comparer à yajl parfois); mais en principe, un regex devrait être plus rapide car il est à l'état fini et beaucoup plus optimisable, au lieu d'un analyseur qui doit supporter la récursion, et dans ce cas, dépense beaucoup D'arbres de construction CPU pour des structures dont vous ne vous souciez pas. (Si quelqu'un a écrit un transducteur d'état fini qui a fait correctement (profondeur limitée) JSON parsing, ce serait fantastique! En attendant, nous avons "grep-o".)

pour écrire du code maintenable, j'utilise toujours une vraie bibliothèque d'analyse. Je n'ai pas essayé jsawk , mais si cela fonctionne bien, cela répondrait au point n ° 1.

une dernière solution, plus farfelue: j'ai écrit un script qui utilise Python json et extrait les clés que vous voulez, dans des colonnes séparées par des onglets; puis je passe à travers un wrapper autour de awk qui permet à named d'accéder aux colonnes. ici: le json2tsv et tsvawk scripts . Donc, pour cet exemple, il serait:

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

cette approche ne tient pas compte #2, est plus inefficace qu'un simple script Python, et c'est un peu fragile: il force la normalisation des lignes et des onglets dans les valeurs string, pour être agréable avec la vue du monde délimitée par le champ/record d'awk. Mais il vous permet de rester sur la ligne de commande, avec plus de justesse que grep -o .

226
répondu Brendan OConnor 2014-03-27 08:12:47

sur la base que certaines des recommandations ici (en particulier dans les commentaires) suggéraient L'utilisation de Python, j'ai été déçu de ne pas trouver un exemple.

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

echo '{"hostname":"test","domainname":"example.com"}' | python -c 'import json,sys;obj=json.load(sys.stdin);print obj[0]["hostname"]'
149
répondu paulkmoore 2014-03-05 20:44:34

suivant L'avance de MartinR et Boecko:

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

qui vous donnera une sortie extrêmement grep friendly. Très pratique:

$ curl -s 'http://twitter.com/users/username.json' | python -mjson.tool | grep my_key
117
répondu jnrg 2016-06-15 12:50:45

vous pouvez juste télécharger jq binaire pour votre plate-forme et exécuter ( chmod +x jq ):

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

il extrait l'attribut "name" de l'objet json.

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

111
répondu jfs 2013-05-30 15:02:49

utilisez le support JSON de Python au lieu d'utiliser awk!

quelque chose comme ça:

curl -s http://twitter.com/users/username.json | \
    python -c "import json,sys;obj=json.load(sys.stdin);print obj['name'];"
88
répondu martinr 2017-03-01 15:00:14

À L'Aide Du Noeud.js

si le système a installé, il est possible d'utiliser les drapeaux -p print et -e evaule script avec JSON.parse pour extraire n'importe quelle valeur qui est nécessaire.

exemple simple utilisant la chaîne JSON { "foo": "bar" } et retirant la valeur de "foo":

$ node -pe 'JSON.parse(process.argv[1]).foo' '{ "foo": "bar" }'
bar

Parce que nous avons accès à cat et autres utilitaires, nous pouvons l'utiliser pour les fichiers:

$ node -pe 'JSON.parse(process.argv[1]).foo' "$(cat foobar.json)"
bar

ou tout autre format tel QU'une URL qui contient JSON:

$ node -pe 'JSON.parse(process.argv[1]).name' "$(curl -s https://api.github.com/users/trevorsenior)"
Trevor Senior
75
répondu x9hb8wcy6quezjk 2013-11-26 14:14:09

vous avez demandé comment vous tirer dans le pied et je suis ici pour fournir les munitions:

curl -s 'http://twitter.com/users/username.json' | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^text/ {print }'

vous pouvez utiliser tr -d '{}' au lieu de sed . Mais en laissant complètement semble avoir l'effet désiré.

si vous voulez enlever les guillemets extérieurs, faites passer le résultat de ce qui précède par sed 's/\(^"\|"$\)//g'

je pense que d'autres ont sonné l'alarme. Je vais être debout avec un téléphone cellulaire pour appeler une ambulance. Tirez quand vous êtes prêts.

44
répondu Dennis Williamson 2009-12-24 00:08:01

utilisant Bash avec Python

créer une fonction bash dans votre .bash_rc file

function getJsonVal () { 
    python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)))"; 
}

puis

$ curl 'http://twitter.com/users/username.json' | getJsonVal "['text']"
My status
$ 

Voici la même fonction, mais avec vérification d'erreur.

function getJsonVal() {
   if [ \( $# -ne 1 \) -o \( -t 0 \) ]; then
       cat <<EOF
Usage: getJsonVal 'key' < /tmp/
 -- or -- 
 cat /tmp/input | getJsonVal 'key'
EOF
       return;
   fi;
   python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)))";
}

où $ # - ne 1 s'assure qu'au moins 1 input, et-t 0 s'assure que vous redirigez à partir d'un tuyau.

la bonne chose à propos de cette implémentation est que vous pouvez accéder aux valeurs JSON imbriquées et obtenez json en retour! = )

exemple:

$ echo '{"foo": {"bar": "baz", "a": [1,2,3]}}' |  getJsonVal "['foo']['a'][1]"
2

si vous voulez être vraiment chic, vous pouvez très bien imprimer les données:

function getJsonVal () { 
    python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin), sort_keys=True, indent=4))"; 
}

$ echo '{"foo": {"bar": "baz", "a": [1,2,3]}}' |  getJsonVal "['foo']"
{
    "a": [
        1, 
        2, 
        3
    ], 
    "bar": "baz"
}
36
répondu Joe Heyming 2016-06-03 16:35:08

Parsing JSON with PHP CLI

sans doute hors sujet mais puisque la préséance règne cette question reste incomplète sans une mention de notre fidèle et fidèle PHP, n'est-ce pas?

utilisant le même exemple JSON mais permet de l'affecter à une variable pour réduire l'obscurité.

$ export JSON='{"hostname":"test","domainname":"example.com"}'

Maintenant, pour PHP bonté, à l'aide de file_get_contents et le php://stdin flux wrapper.

$ echo $JSON|php -r 'echo json_decode(file_get_contents("php://stdin"))->hostname;'

ou comme l'a souligné à l'aide de fgets et déjà ouvert des cours d'eau à la CLI constante STDIN .

$ echo $JSON|php -r 'echo json_decode(fgets(STDIN))->hostname;'

nJoy!

19
répondu nickl- 2013-04-22 12:51:24

TickTick est un JSON parser écrit en bash (<250 lignes de code)

voici un extrait de l'article de L'auteur, Imaginez un monde où Bash soutient JSON :

#!/bin/bash
. ticktick.sh

``  
  people = { 
    "Writers": [
      "Rod Serling",
      "Charles Beaumont",
      "Richard Matheson"
    ],  
    "Cast": {
      "Rod Serling": { "Episodes": 156 },
      "Martin Landau": { "Episodes": 2 },
      "William Shatner": { "Episodes": 2 } 
    }   
  }   
``  

function printDirectors() {
  echo "  The ``people.Directors.length()`` Directors are:"

  for director in ``people.Directors.items()``; do
    printf "    - %s\n" ${!director}
  done
}   

`` people.Directors = [ "John Brahm", "Douglas Heyes" ] ``
printDirectors

newDirector="Lamont Johnson"
`` people.Directors.push($newDirector) ``
printDirectors

echo "Shifted: "``people.Directors.shift()``
printDirectors

echo "Popped: "``people.Directors.pop()``
printDirectors
18
répondu CoolAJ86 2014-06-12 01:41:34

version Native Bash: Fonctionne aussi bien avec backslashs ( \ ) et guillemets (")

function parse_json()
{
    echo  | \
    sed -e 's/[{}]/''/g' | \
    sed -e 's/", "/'\",\"'/g' | \
    sed -e 's/" ,"/'\",\"'/g' | \
    sed -e 's/" , "/'\",\"'/g' | \
    sed -e 's/","/'\"---SEPERATOR---\"'/g' | \
    awk -F=':' -v RS='---SEPERATOR---' "$1~/\"\"/ {print}" | \
    sed -e "s/\"\"://" | \
    tr -d "\n\t" | \
    sed -e 's/\"/"/g' | \
    sed -e 's/\\/\/g' | \
    sed -e 's/^[ \t]*//g' | \
    sed -e 's/^"//'  -e 's/"$//'
}


parse_json '{"username":"john, doe","email":"john@doe.com"}' username
parse_json '{"username":"john doe","email":"john@doe.com"}' email

--- outputs ---

john, doe
johh@doe.com
17
répondu maikel 2015-03-12 20:43:56

Version qui utilise Ruby et http://flori.github.com/json /

$ < file.json ruby -e "require 'rubygems'; require 'json'; puts JSON.pretty_generate(JSON[STDIN.read]);"

ou plus concise:

$ < file.json ruby -r rubygems -r json -e "puts JSON.pretty_generate(JSON[STDIN.read]);"
11
répondu boecko 2016-04-27 01:44:18

vous pouvez utiliser jshon :

curl 'http://twitter.com/users/username.json' | jshon -e text
5
répondu kev 2012-04-11 14:48:10

malheureusement la réponse la plus votée qui utilise grep renvoie le complet match qui n'a pas fonctionné dans mon scénario, mais si vous savez que le format JSON restera constant, vous pouvez utiliser lookbehind et lookahead pour extraire juste les valeurs désirées.

# echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="FooBar":")(.*?)(?=",)'
he\"llo
# echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="TotalPages":)(.*?)(?=,)'
33
#  echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="anotherValue":)(.*?)(?=})'
100
5
répondu Daniel Sokolowski 2016-12-16 18:20:54

voici un moyen que vous pouvez le faire avec awk

curl -sL 'http://twitter.com/users/username.json' | awk -F"," -v k="text" '{
    gsub(/{|}/,"")
    for(i=1;i<=NF;i++){
        if ( $i ~ k ){
            print $i
        }
    }
}'
4
répondu ghostdog74 2009-12-24 00:08:48

Quelqu'un qui a aussi des fichiers xml, pourrait vouloir regarder mon Xidel . C'est un cli, sans dépendance jsoniq processeur. (il prend également en charge XQuery pour en xml ou json traitement)

l'exemple dans La question serait:

 xidel -e 'json("http://twitter.com/users/username.json")("name")'

ou avec ma propre syntaxe d'extension non standard:

 xidel -e 'json("http://twitter.com/users/username.json").name'
4
répondu BeniBela 2013-05-30 17:09:01

pour l'analyse JSON plus complexe, je suggère d'utiliser le module python jsonpath (par Stefan Goessner) -

  1. Installer

sudo easy_install-U jsonpath

  1. Utiliser

exemple de fichier.json (de http://goessner.net/articles/JsonPath ) -

{ "store": {
    "book": [ 
      { "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

analyse (extraire tous les titres avec le prix < 10) -

$ cat file.json | python -c "import sys, json, jsonpath; print '\n'.join(jsonpath.jsonpath(json.load(sys.stdin), 'store.book[?(@.price < 10)].title'))"

sortie Will -

Sayings of the Century
Moby Dick

NOTE: la ligne de commande ci-dessus ne comprend pas la vérification des erreurs. pour une solution complète avec vérification des erreurs, vous devez créer un petit script python, et envelopper le code avec try-except.

4
répondu shlomosh 2014-04-01 09:05:56

si vous avez php :

php -r 'var_export(json_decode(`curl http://twitter.com/users/username.json`, 1));'

par exemple:

nous disposons d'une ressource qui fournit à json les codes iso des pays: http://country.io/iso3.json et nous pouvons facilement le voir dans une coquille avec boucle:

curl http://country.io/iso3.json

mais il semble pas très pratique, et pas lisible, mieux parse json et voir la structure lisible:

php -r 'var_export(json_decode(`curl http://country.io/iso3.json`, 1));'

ce code imprimera quelque chose comme:

array (
  'BD' => 'BGD',
  'BE' => 'BEL',
  'BF' => 'BFA',
  'BG' => 'BGR',
  'BA' => 'BIH',
  'BB' => 'BRB',
  'WF' => 'WLF',
  'BL' => 'BLM',
  ...

si vous avez des tableaux imbriqués cette sortie est beaucoup mieux...

espérons que cela sera utile...

4
répondu Vladimir Kovpak 2015-11-19 11:03:25

vous pouvez essayer quelque chose comme ça -

curl -s 'http://twitter.com/users/jaypalsingh.json' | 
awk -F=":" -v RS="," '~/"text"/ {print}'
3
répondu jaypal singh 2011-12-06 23:39:03

Parsing JSON est douloureux dans une écriture shell. Avec un langage plus approprié, créez un outil qui extrait les attributs JSON d'une manière compatible avec les conventions de script shell. Vous pouvez utiliser votre nouvel outil pour résoudre le immédiate de scripts shell problème, puis l'ajouter à votre kit pour des situations futures.

par exemple, considérer un outil jsonlookup tel que si je dis jsonlookup access token id il retournera l'attribut id défini dans l'attribut token défini dans l'attribut access de stdin, qui est probablement des données JSON. Si l'attribut n'existe pas, l'outil renvoie rien (sortie d'état 1). Si l'analyse échoue, quittez l'état 2 et un message à stderr. Si la recherche réussit, l'outil imprime la valeur de l'attribut.

ayant créé un outil unix dans le but précis d'extraire les valeurs JSON, vous pouvez facilement l'utiliser dans shell scripts:

access_token=$(curl <some horrible crap> | jsonlookup access token id)

N'importe quelle langue fera pour la mise en œuvre de jsonlookup . Voici une version python assez concise:

#!/usr/bin/python                                                               

import sys
import json

try: rep = json.loads(sys.stdin.read())
except:
    sys.stderr.write(sys.argv[0] + ": unable to parse JSON from stdin\n")
    sys.exit(2)
for key in sys.argv[1:]:
    if key not in rep:
        sys.exit(1)
    rep = rep[key]
print rep
3
répondu mcnabicus 2014-02-02 21:28:01

un double-liner qui utilise python. Cela fonctionne particulièrement bien si vous écrivez un single .sh file et vous ne voulez pas dépendre d'un autre .dossier py. Il tire également profit de l'utilisation de la pipe | . echo "{\"field\": \"value\"}" peut être remplacé par tout ce qui imprime un json au stdout.

echo "{\"field\": \"value\"}" | python -c 'import sys, json
print(json.load(sys.stdin)["field"])'
3
répondu Adam Kurkiewicz 2014-12-04 17:47:39

c'est une bonne usecase pour pythonpy :

curl 'http://twitter.com/users/username.json' | py 'json.load(sys.stdin)["name"]'
3
répondu RussellStewart 2015-03-27 20:25:55

si pip est disponible sur le système alors:

$ pip install json-query

exemples d'utilisation:

$ curl -s http://0/file.json | json-query
{
    "key":"value"    
}

$ curl -s http://0/file.json | json-query my.key
value

$ curl -s http://0/file.json | json-query my.keys.
key_1
key_2
key_3

$ curl -s http://0/file.json | json-query my.keys.2
value_2
3
répondu Alexey Dubkov 2016-08-27 04:37:44

maintenant que Powershell est une plateforme croisée, j'ai pensé que j'allais m'y aventurer, car je trouve que C'est assez intuitif et extrêmement simple.

curl -s 'https://api.github.com/users/lambda' | ConvertFrom-Json 

ConvertFrom-JSON convertit le JSON en un objet personnalisé Powershell, de sorte que vous pouvez facilement travailler avec les propriétés à partir de ce point en avant. Si vous vouliez seulement la propriété 'id' par exemple, vous feriez juste ceci:

curl -s 'https://api.github.com/users/lambda' | ConvertFrom-Json | select -ExpandProperty id

si vous vouliez invoquer toute la chose de l'intérieur Bash, alors tu devrais l'appeler comme ça:

powershell 'curl -s "https://api.github.com/users/lambda" | ConvertFrom-Json'

bien sûr, il y a une façon Powershell pure de le faire sans curl, qui serait:

Invoke-WebRequest 'https://api.github.com/users/lambda' | select -ExpandProperty Content | ConvertFrom-Json

enfin, il y a aussi' ConvertTo-Json ' qui convertit un objet personnalisé en JSON aussi facilement. Voici un exemple:

(New-Object PsObject -Property @{ Name = "Tester"; SomeList = @('one','two','three')}) | ConvertTo-Json

qui produirait un joli JSON comme celui-ci:

{
"Name":  "Tester",
"SomeList":  [
                 "one",
                 "two",
                 "three"
             ]

}

certes, en utilisant un Windows shell sur Unix est un peu sacrilège mais Powershell est vraiment bon à certaines choses, et parsing JSON et XML sont un couple d'entre eux. C'est la page GitHub pour la version cross plate-forme https://github.com/PowerShell/PowerShell

3
répondu user2233949 2017-03-20 12:37:44

C'est encore une autre réponse hybride bash & python . J'ai posté cette réponse parce que je voulais traiter des sorties JSON plus complexes, mais en réduisant la complexité de mon application bash. Je veux ouvrir l'objet JSON suivant de http://www.arcgis.com/sharing/rest/info?f=json in bash :

{
  "owningSystemUrl": "http://www.arcgis.com",
  "authInfo": {
    "tokenServicesUrl": "https://www.arcgis.com/sharing/rest/generateToken",
    "isTokenBasedSecurity": true
  }
}

alors que cette approche augmente la complexité de la fonction Python, l'utilisation de bash devient plus simple:

function jsonGet {
  python -c 'import json,sys
o=json.load(sys.stdin)
k="''"
if k != "":
  for a in k.split("."):
    if isinstance(o, dict):
      o=o[a] if a in o else ""
    elif isinstance(o, list):
      if a == "length":
        o=str(len(o))
      elif a == "join":
        o=",".join(o)
      else:
        o=o[int(a)]
    else:
      o=""
if isinstance(o, str) or isinstance(o, unicode):
  print o
else:
  print json.dumps(o)
'
}

curl -s http://www.arcgis.com/sharing/rest/info?f=json | jsonGet
curl -s http://www.arcgis.com/sharing/rest/info?f=json | jsonGet authInfo
curl -s http://www.arcgis.com/sharing/rest/info?f=json | jsonGet authInfo.tokenServicesUrl

la sortie du script ci-dessus est:

j'ai ajouté le support pour les tableaux, de sorte que vous pouvez utiliser .length et, si la source est un tableau de chaîne de caractères, vous pouvez utiliser .join :

curl -s http://www.arcgis.com/sharing/rest/portals/self?f=pjson | jsonGet defaultBasemap.baseMapLayers.length
curl -s http://www.arcgis.com/sharing/rest/portals/self?f=pjson | jsonGet defaultBasemap.baseMapLayers.0.resourceInfo.tileInfo.lods
curl -s http://www.arcgis.com/sharing/rest/portals/self?f=pjson | jsonGet defaultBasemap.baseMapLayers.0.resourceInfo.tileInfo.lods.length
curl -s http://www.arcgis.com/sharing/rest/portals/self?f=pjson | jsonGet defaultBasemap.baseMapLayers.0.resourceInfo.tileInfo.lods.23

qui produit:

  • 1
  • [{"échelle": 591657527.591555, "résolution": 156543.03392800014, le "niveau": 0}, {"échelle": 295828763.795777, "résolution": 78271.51696399994, le "niveau": 1}, {"échelle": 147914381.897889, "résolution": 39135.75848200009, le "niveau": 2}, {"échelle": 73957190.948944, "résolution": 19567.87924099992, le "niveau": 3}, {"échelle": 36978595.474472, "résolution": 9783.93962049996, le "niveau": 4}, {"échelle": 18489297.737236, "résolution": 4891.96981024998, le "niveau": 5}, {"échelle": 9244648.868618, "résolution": 2445.98490512499, le "niveau": 6}, {"échelle": 4622324.434309, "résolution": 1222.992452562495, le "niveau": 7}, {"échelle": 2311162.217155, "résolution": 611.4962262813797, le "niveau": 8}, {"échelle": 1155581.108577, "résolution": 305.74811314055756, le "niveau": 9}, {"échelle": 577790.554289, "résolution": 152.87405657041106, le "niveau": 10}, {"échelle": 288895.277144, "résolution": 76.43702828507324, le "niveau": 11}, {"échelle": 144447.638572, "résolution": 38.21851414253662, le "niveau": 12}, {"échelle": 72223.819286, "résolution": 19.10925707126831, le "niveau": 13}, {"échelle": 36111.909643, "résolution": 9.554628535634155, le "niveau": 14}, {"échelle": 18055.954822, "résolution": 4.77731426794937, le "niveau": 15}, {"échelle": 9027.977411, "résolution": 2.388657133974685, le "niveau": 16}, {"échelle": 4513.988705, "résolution": 1.1943285668550503, le "niveau": 17}, {"échelle": 2256.994353, "résolution": 0.5971642835598172, le "niveau": 18}, {"échelle": 1128.497176, "résolution": 0.29858214164761665, le "niveau": 19}, {"échelle": 564.248588, "résolution": 0.14929107082380833, le "niveau": 20}, {"échelle": 282.124294, "résolution": 0.07464553541190416, le "niveau": 21}, {"échelle": 141.062147, "résolution": 0.03732276770595208, le "niveau": 22}, {"échelle": 70.5310735, "résolution": 0.01866138385297604, le "niveau": 23}]
  • 24
  • {"échelle": 70.5310735, "résolution": 0.01866138385297604, le "niveau": 23}
3
répondu Stephen Quan 2017-07-19 21:23:25

si quelqu'un veut simplement extraire des valeurs à partir de simples objets JSON sans avoir besoin de structures imbriquées, il est possible d'utiliser des expressions régulières sans même quitter la base.

Voici une fonction que j'ai définie en utilisant des expressions régulières bash basées sur la norme JSON :

function json_extract() {
  local key=
  local json=

  local string_regex='"([^"\]|\.)*"'
  local number_regex='-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?'
  local value_regex="${string_regex}|${number_regex}|true|false|null"
  local pair_regex="\"${key}\"[[:space:]]*:[[:space:]]*(${value_regex})"

  if [[ ${json} =~ ${pair_regex} ]]; then
    echo $(sed 's/^"\|"$//g' <<< "${BASH_REMATCH[1]}")
  else
    return 1
  fi
}

mises en garde: les objets et les tableaux ne sont pas pris en charge en tant que valeur, mais tous les autres types de valeur définis dans la norme sont pris en charge. De plus, une paire sera appariée peu importe la profondeur du document JSON, pourvu qu'il ait exactement le même nom de clé.

utilisant L'exemple de OP:

$ json_extract text "$(curl 'http://twitter.com/users/username.json')"
My status

$ json_extract friends_count "$(curl 'http://twitter.com/users/username.json')"
245
3
répondu Helder Pereira 2017-09-20 14:33:32

Voici une bonne référence . Dans ce cas:

curl 'http://twitter.com/users/username.json' | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split("151900920",a,","); for (i=1; i<=n; i++) { where = match(a[i], /\"text\"/); if(where) {print a[i]} }  }'
2
répondu Max Barrass 2015-05-25 04:04:43

Niet est un outil qui vous aide à extraire des données à partir du fichier JSON ou yaml directement dans votre shell/bash CLI.

$ pip install niet

considérez un fichier json nommé project.json avec le contenu suivant:

{
  project: {
    meta: {
      name: project-sample
    }
}

vous pouvez utiliser niet comme ceci:

$ PROJECT_NAME=$(niet project.json project.meta.name)
$ echo ${PROJECT_NAME}
project-sample
2
répondu Herve 2018-02-12 15:52:14

j'ai utilisé ceci pour extraire la durée vidéo de la sortie ffprobe json:

MOVIE_INFO=`ffprobe "path/to/movie.mp4"  -show_streams -show_format -print_format json -v quiet` 
MOVIE_SECONDS=`echo "$MOVIE_INFO"|grep -w \"duration\" |tail -1 | cut -d\" -f4 |cut -d \. -f 1`

il peut être utilisé pour extraire une valeur de n'importe quel json:

value=`echo "$jsondata"|grep -w \"key_name\" |tail -1 | cut -d\" -f4
2
répondu Ehsan Chavoshi 2018-06-19 13:20:02