Parsowanie JSON z narzędziami Unix

Próbuję przetworzyć JSON zwrócony z żądania curl, w ten sposób:

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]}'

Powyższe dzieli JSON na pola, na przykład:

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

Jak wydrukować określone pole (oznaczone przez -v k=text)?

Author: codeforester, 2009-12-24

30 answers

Istnieje wiele narzędzi zaprojektowanych specjalnie w celu manipulowania JSON z linii poleceń, i będzie o wiele łatwiejsze i bardziej niezawodne niż robienie tego z Awk, takie jakjq:

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

Możesz to zrobić również za pomocą narzędzi, które prawdopodobnie są już zainstalowane w Twoim systemie, takich jak Python przy użyciu json module , a więc unikaj dodatkowych zależności, mając jednocześnie korzyść z właściwego parsera JSON. Poniższe założenie zakłada, że chcesz użyć UTF-8, w którym powinien być zakodowany oryginalny JSON i jest tym, czego używa większość nowoczesnych terminali:

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'])"

Zapiski historyczne

Ta odpowiedź pierwotnie zalecała jsawk , który nadal powinien działać, ale jest trochę bardziej kłopotliwy w użyciu niż jq i zależy od zainstalowanego samodzielnego interpretera JavaScript, który jest mniej powszechny niż interpreter Pythona, więc powyższe odpowiedzi są prawdopodobnie "Type": "content"]}

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

Ta odpowiedź również pierwotnie używała API Twitter z pytania, ale to API nie działa, co sprawia, że trudno jest skopiować przykłady do przetestowania, a nowe Api Twitter wymaga kluczy API, więc przełączyłem się na korzystanie z API GitHub, które można łatwo używać bez kluczy API. Pierwsza odpowiedź na pierwotne pytanie brzmiałaby:

curl 'http://twitter.com/users/username.json' | jq -r '.text'
 671
Author: Brian Campbell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-09 18:06:18

Aby szybko wyodrębnić wartości dla konkretnego klucza, osobiście lubię używać "grep-o", który zwraca tylko dopasowanie regex. Na przykład, aby uzyskać pole "tekst" z tweetów, coś w stylu:

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

Ten regex jest bardziej wytrzymały niż mogłoby się wydawać; na przykład, radzi sobie dobrze z ciągami zawierającymi osadzone przecinki i unikalne cudzysłowy wewnątrz nich. Myślę, że z trochę więcej pracy można zrobić taki, który jest rzeczywiście gwarantowane, aby wydobyć wartość, jeśli jest atomowy. (Jeśli ma zagnieżdżanie, wtedy regex nie może tego oczywiście zrobić.)

I do dalszego czyszczenia (aczkolwiek zachowując oryginalny ciąg znaków ucieczki) możesz użyć czegoś takiego jak: | perl -pe 's/"text"://; s/^"//; s/",$//'. (Zrobiłem to dla tej analizy.)

Do wszystkich hejterów, którzy nalegają, aby używać prawdziwego parsera JSON -- tak, to jest niezbędne dla poprawności, ale

  1. aby zrobić naprawdę szybką analizę, jak liczenie wartości, aby sprawdzić błędy czyszczenia danych lub uzyskać ogólne wyczucie danych, Walić coś na wiersz poleceń jest szybszy. Otwieranie edytora w celu napisania skryptu jest rozpraszające.
  2. {[3] } jest o rzędy wielkości szybsza niż standardowa biblioteka Pythona json, przynajmniej gdy robi to dla tweetów (które są ~2 KB każdy). Nie jestem pewien, czy jest to tylko dlatego, że json jest powolny (powinienem kiedyś porównać do yajla); ale w zasadzie regex powinien być szybszy, ponieważ jest skończony i znacznie bardziej optymalny, zamiast parsera, który musi obsługiwać rekursję, a w tym przypadku wydaje dużo CPU budujesz drzewa dla budowli, na których Ci nie zależy. (Gdyby ktoś napisał przetwornik typu finite state, który wykonał poprawne (ograniczone do głębokości) parsowanie JSON, byłoby fantastycznie! W międzyczasie mamy "grep-o".)

Aby napisać możliwy do utrzymania kod, zawsze używam prawdziwej biblioteki parsującej. Nie próbowałem jsawk, ale jeśli to działa dobrze, to adresuje punkt # 1.

Ostatnie, bardziej zwariowane rozwiązanie: napisałem skrypt, który używa Pythona json i wyodrębnia klucze, które chcesz, do kolumny oddzielone tabulatorami; następnie przechodzę przez owijarkę wokół awk, która umożliwia nazwany dostęp do kolumn. tutaj: Skrypty json2tsv i tsvawk . Więc dla tego przykładu byłoby to:

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

To podejście nie odnosi się do #2, jest bardziej nieefektywne niż pojedynczy skrypt Pythona i jest trochę kruche: wymusza normalizację nowych linii i tabulatorów w wartościach łańcuchowych, aby grać przyjemnie z widokiem świata rozdzielanym polami/rekordami awk. Ale to pozwala pozostać w wierszu poleceń, z większą poprawnością niż grep -o.

 226
Author: Brendan OConnor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-27 08:12:47

Na podstawie tego, że niektóre z poniższych zaleceń (esp w komentarzach) sugerowały użycie Pythona, byłem rozczarowany, że nie znalazłem przykładu.

Oto jedna linijka, aby uzyskać pojedynczą wartość z niektórych danych JSON. Zakłada ona, że przesyłasz dane (skądś) i dlatego powinna być przydatna w kontekście skryptowym.

echo '{"hostname":"test","domainname":"example.com"}' | python -c 'import json,sys;obj=json.load(sys.stdin);print obj[0]["hostname"]'
 149
Author: paulkmoore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-05 20:44:34

Po śladach Martinra i Boecko:

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

To daje bardzo przyjazny dla grepa wynik. Bardzo wygodne:

$ curl -s 'http://twitter.com/users/username.json' | python -mjson.tool | grep my_key
 117
Author: jnrg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-15 12:50:45

Możesz po prostu pobrać jq binarny dla swojej platformy i uruchomić (chmod +x jq):

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

Wyodrębnia "name" atrybut z obiektu json.

jq Strona główna mówi, że jest jak sed dla danych JSON.

 111
Author: jfs,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-30 15:02:49

Użyj Obsługa Pythona JSON zamiast używać awk!

Coś takiego:

curl -s http://twitter.com/users/username.json | \
    python -c "import json,sys;obj=json.load(sys.stdin);print obj['name'];"
 88
Author: martinr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-01 15:00:14

Korzystanie Z Węzła.js

Jeśli system ma zainstalowany węzeł , możliwe jest użycie znaczników -p print i -e evaulate script z JSON.parse aby wyciągnąć dowolną wartość, która jest potrzebna.

Prosty przykład użycia ciągu JSON { "foo": "bar" } i wyciągnięcia wartości "foo":

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

Ponieważ mamy dostęp do cat i innych narzędzi, możemy użyć tego do plików:

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

Lub jakikolwiek inny format, taki jak adres URL zawierający JSON:

$ node -pe 'JSON.parse(process.argv[1]).name' "$(curl -s https://api.github.com/users/trevorsenior)"
Trevor Senior
 75
Author: x9hb8wcy6quezjk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-26 14:14:09

Zapytałeś jak strzelić sobie w stopę, a ja Jestem tu, aby dostarczyć amunicję:

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

Możesz użyć tr -d '{}' zamiast sed. Ale pomijając je całkowicie wydaje się mieć pożądany efekt, jak również.

Jeśli chcesz usunąć zewnętrzne cudzysłowy, prześlij wynik powyższego przez sed 's/\(^"\|"$\)//g'

Myślę, że inni alarmowali wystarczająco. Będę czekał z komórką, żeby wezwać karetkę. Strzelaj, gdy będziesz gotowy.
 44
Author: Dennis Williamson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-24 00:08:01

Używanie Basha z Pythonem

Utwórz funkcję bash w swoim .plik bash_rc

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

Then

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

Tutaj jest ta sama funkcja, ale z sprawdzaniem błędów.

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)$1))";
}

Gdzie $ # - ne 1 zapewnia co najmniej 1 wejście, A -t 0 upewnia się, że przekierowujesz z rury.

Fajną rzeczą w tej implementacji jest to, że możesz uzyskać dostęp do zagnieżdżonych wartości json i uzyskać json w zamian! =)

Przykład:

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

Jeśli chcesz być naprawdę fantazyjny, możesz ładny wydruk danych:

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

$ echo '{"foo": {"bar": "baz", "a": [1,2,3]}}' |  getJsonVal "['foo']"
{
    "a": [
        1, 
        2, 
        3
    ], 
    "bar": "baz"
}
 36
Author: Joe Heyming,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-03 16:35:08

Parsowanie JSON z PHP CLI

Prawdopodobnie off topic, ale ponieważ króluje pierwszeństwo, to pytanie pozostaje niekompletne bez wzmianki o naszym wiernym i wiernym PHP, mam rację?

Używając tego samego przykładu JSON, ale pozwala przypisać go do zmiennej, aby zmniejszyć zaciemnienie.

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

Teraz dla PHP, używając file_get_contents i php://stdin stream wrapper.

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

Lub jak wskazano za pomocą fgets i już otwartego strumienia na Stała CLI STDIN.

$ echo $JSON|php -r 'echo json_decode(fgets(STDIN))->hostname;'
NJoy!
 19
Author: nickl-,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-22 12:51:24

TickTick jest parserem JSON napisanym w bash (

Oto fragment artykułu autora, wyobraź sobie świat, w którym Bash obsługuje 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
Author: CoolAJ86,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-12 01:41:34

Natywna wersja Bash: Działa również dobrze z odwrotnymi ukośnikami ( \ ) i cudzysłowami (")

function parse_json()
{
    echo $1 | \
    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~/\"$2\"/ {print}" | \
    sed -e "s/\"$2\"://" | \
    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":"[email protected]"}' username
parse_json '{"username":"john doe","email":"[email protected]"}' email

--- outputs ---

john, doe
[email protected]
 17
Author: maikel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-12 20:43:56

Wersja, która używa Ruby i http://flori.github.com/json/

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

Lub bardziej zwięźle:

$ < file.json ruby -r rubygems -r json -e "puts JSON.pretty_generate(JSON[STDIN.read]);"
 11
Author: boecko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-27 01:44:18

Możesz użyć jshon:

curl 'http://twitter.com/users/username.json' | jshon -e text
 5
Author: kev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-11 14:48:10

Niestety najczęściej głosowana odpowiedź, która używa grepzwraca pełnedopasowanie, które nie zadziałało w moim scenariuszu, ale jeśli wiesz, że format JSON pozostanie stały, możesz użyć lookbehindi lookahead, aby wyodrębnić tylko pożądane wartości.

# 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
Author: Daniel Sokolowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-16 18:20:54

Oto jeden sposób, w jaki możesz to zrobić z 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
Author: ghostdog74,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-24 00:08:48

Ktoś, kto ma również pliki xml, może chcieć spojrzeć na mój Xidel . Jest to cli, bez zależności jsoniq procesor. (tj. obsługuje również XQuery do przetwarzania xml lub json)

Przykład w pytaniu brzmiałby:

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

Lub z własną, niestandardową składnią rozszerzenia:

 xidel -e 'json("http://twitter.com/users/username.json").name'
 4
Author: BeniBela,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-30 17:09:01

Dla bardziej skomplikowanego parsowania JSON proponuję użycie modułu python jsonpath (by Stefan Goessner)-

  1. Install it -

Sudo easy_install-U jsonpath

  1. Użyj go -

Przykładowy plik.json (from 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
    }
  }
}

Parse it (Wyodrębnij wszystkie tytuły książek z ceną

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

Will output -

Sayings of the Century
Moby Dick

Uwaga: powyższy wiersz poleceń nie zawiera sprawdzania błędów. pełne rozwiązanie po sprawdzaniu błędów należy utworzyć mały skrypt Pythona i zawinąć kod za pomocą try-except.

 4
Author: shlomosh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-01 09:05:56

Jeśli masz php:

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

Na przykład:
mamy zasób, który zapewnia json kody iso krajów: http://country.io/iso3.json i możemy go łatwo zobaczyć w skorupie z curl:

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

Ale nie wygląda to zbyt wygodnie i nie jest czytelne, lepiej parsuj json i zobacz czytelną strukturę:

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

Ten kod wydrukuje coś w stylu:

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

Jeśli macie zagnieżdżone Tablice to wyjście będzie wyglądało znacznie lepiej...

Hope this will pomocne...

 4
Author: Vladimir Kovpak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-19 11:03:25

Możesz spróbować czegoś takiego -

curl -s 'http://twitter.com/users/jaypalsingh.json' | 
awk -F=":" -v RS="," '$1~/"text"/ {print}'
 3
Author: jaypal singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-06 23:39:03

Parsowanie JSON jest bolesne w skrypcie powłoki. Używając bardziej odpowiedniego języka, Utwórz narzędzie, które wyodrębnia atrybuty JSON w sposób zgodny z konwencjami skryptów powłoki. Możesz użyć nowego narzędzia do rozwiązania natychmiastowego problemu ze skryptami powłoki, a następnie dodać go do zestawu w przyszłych sytuacjach.

Na przykład rozważ narzędzie jsonlookup takie, że jeśli powiem jsonlookup access token id zwróci atrybut id zdefiniowany w atrybucie token zdefiniowanym w atrybut access ze stdin, czyli przypuszczalnie danych JSON. Jeśli atrybut nie istnieje, narzędzie nie zwraca nic(status zakończenia 1). Jeśli parsowanie nie powiedzie się, Zakończ stan 2 i wyślij wiadomość na stderr. Jeśli Wyszukiwanie się powiedzie, narzędzie wyświetli wartość atrybutu.

Po stworzeniu narzędzia uniksowego do dokładnego wyodrębniania wartości JSON można z łatwością używać go w skryptach powłoki:

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

Każdy język zrobi dla implementacji jsonlookup . Oto dość zwięzła wersja Pythona:

#!/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
Author: mcnabicus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-02 21:28:01

Dwuliniowy, który używa Pythona. Działa szczególnie dobrze, jeśli piszesz pojedynczy plik. sh i nie chcesz polegać na innym pliku. py. Wykorzystuje również użycie pipe |. echo "{\"field\": \"value\"}" może być zastąpiony przez cokolwiek drukującego json na stdout.

echo "{\"field\": \"value\"}" | python -c 'import sys, json
print(json.load(sys.stdin)["field"])'
 3
Author: Adam Kurkiewicz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-04 17:47:39

To jest dobry usecase dla pythonpy :

curl 'http://twitter.com/users/username.json' | py 'json.load(sys.stdin)["name"]'
 3
Author: RussellStewart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-27 20:25:55

Jeśli pip jest dostępne w systemie to:

$ pip install json-query

Przykłady użycia:

$ 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
Author: Alexey Dubkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-27 04:37:44

Teraz, gdy Powershell jest wieloplatformowy, pomyślałem, że rzucę go tam, ponieważ uważam, że jest dość intuicyjny i niezwykle prosty.

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

ConvertFrom-Json konwertuje JSON na obiekt Niestandardowy Powershell, dzięki czemu można łatwo pracować z właściwościami od tego momentu. Jeśli na przykład chcesz mieć tylko właściwość 'id', po prostu zrób to:

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

Jeśli chcesz wywołać całość z Basha, musisz to nazwać tak to:

powershell 'curl -s "https://api.github.com/users/lambda" | ConvertFrom-Json'
Oczywiście istnieje czysty Powershellowy sposób na zrobienie tego bez curla, czyli:]}
Invoke-WebRequest 'https://api.github.com/users/lambda' | select -ExpandProperty Content | ConvertFrom-Json

Wreszcie, istnieje również 'ConvertTo-Json', który równie łatwo konwertuje obiekt niestandardowy na JSON. Oto przykład:

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

Co by dało fajny JSON taki:

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

}

Co prawda używanie powłoki Windows na Uniksie jest nieco świętokradzkie, ale Powershell jest naprawdę dobry w niektórych rzeczach, a parsowanie JSON i XML to kilka z nich. This the Strona GitHub dla wersji cross platform https://github.com/PowerShell/PowerShell

 3
Author: user2233949,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-20 12:37:44

To jest jeszcze jeden bash & python odpowiedź hybrydowa. Opublikowałem tę odpowiedź, ponieważ chciałem przetwarzać bardziej złożone wyjście JSON, ale zmniejszając złożoność mojej aplikacji bash. Chcę otworzyć następujący obiekt JSON z http://www.arcgis.com/sharing/rest/info?f=json W bash:

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

Podczas gdy to podejście zwiększa złożoność funkcji Pythona, użycie bash staje się prostsze:

function jsonGet {
  python -c 'import json,sys
o=json.load(sys.stdin)
k="'$1'"
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

Wyjście powyższego skryptu jest:

Dodałem wsparcie dla tablic, więc można użyć .length i, jeśli źródło jest tablicą łańcuchową, można użyć .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

Które wyjście:

  • 1
  • [{"scale": 591657527.591555, "resolution": 156543.03392800014, "level": 0}, {"scale": 295828763.795777, "resolution": 78271.51696399994, "level": 1}, {"scale": 147914381.897889, "rozdzielczość": 39135.75848200009, "poziom": 2}, {"skala": 73957190.948944, "rozdzielczość": 19567.87924099992, "poziom": 3}, {"skala": 36978595.474472, "rozdzielczość": 9783.93962049996, "level": 4}, {"scale": 18489297.737236, "rozdzielczość": 4891.96981024998, "poziom": 5}, {"skala": 9244648.868618, "rozdzielczość": 2445.98490512499, "poziom": 6}, {"skala": 4622324.434309, "rozdzielczość": 1222.992452562495, "poziom": 7}, {"skala": 2311162.217155, "rozdzielczość": 611.4962262813797, "poziom": 8}, {"skala": 1155581.108577, "rozdzielczość": 305.74811314055756, "poziom": 9}, {"skala": 577790.554289, "rozdzielczość": 152.87405657041106, "poziom": 10}, {"skala": 288895.277144, "rozdzielczość": 76.43702828507324, "poziom": 11}, {"scale": 144447.638572, "resolution": 38.21851414253662, "level": 12}, {"scale": 72223.819286, "resolution": 19.10925707126831, "level": 13}, {"scale": 36111.909643, "resolution": 9.554628535634155, "poziom": 14}, {"skala": 18055.954822, "rozdzielczość": 4.77731426794937, "poziom": 15}, {"skala": 9027.977411, "rozdzielczość": 2.388657133974685, "poziom": 16}, {"skala": 4513.988705, "rozdzielczość": 1.1943285668550503, "poziom": 17}, {"skala": 2256.994353, "rozdzielczość": 0.5971642835598172, "poziom": 18}, {"scale": 1128.497176, "resolution": 0.29858214164761665, "level": 19}, {"scale": 564.248588, "resolution": 0.14929107082380833, "level": 20}, {"scale": 282.124294, "resolution": 0.07464553541190416, "poziom": 21}, {"skala": 141.062147, "rozdzielczość": 0.03732276770595208, "poziom": 22}, {"skala": 70.5310735, "rozdzielczość": 0.01866138385297604, "poziom": 23}]
  • 24
  • {"skala": 70.5310735," rozdzielczość": 0.01866138385297604," poziom": 23}
 3
Author: Stephen Quan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-19 21:23:25

Jeśli ktoś chce po prostu wyodrębnić wartości z prostych obiektów JSON bez potrzeby zagnieżdżania struktur, można używać wyrażeń regularnych nawet bez opuszczania bash.

Oto funkcja zdefiniowana przy użyciu wyrażeń regularnych bash opartych na standardzie JSON :

function json_extract() {
  local key=$1
  local json=$2

  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
}

Zastrzeżenia: obiekty i tablice nie są obsługiwane jako wartość, ale wszystkie inne typy wartości zdefiniowane w standardzie są obsługiwane. Ponadto para zostanie dopasowana bez względu na to, jak głęboko w JSON dokument jest tak długo, jak ma dokładnie tę samą nazwę klucza.

Używając przykładu 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
Author: Helder Pereira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-20 14:33:32

Oto dobre odniesienie . W tym przypadku:

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++) { where = match(a[i], /\"text\"/); if(where) {print a[i]} }  }'
 2
Author: Max Barrass,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-25 04:04:43

Niet {[5] } to narzędzie, które pomoże Ci wyodrębnić dane z pliku JSON lub yaml bezpośrednio do powłoki / bash CLI.

$ pip install niet

Rozważ plik JSON o nazwie project.json o następującej treści:

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

Możesz użyć niet tak:

$ PROJECT_NAME=$(niet project.json project.meta.name)
$ echo ${PROJECT_NAME}
project-sample
 2
Author: Herve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-12 15:52:14

Użyłem tego do wyodrębnienia czasu trwania wideo z wyjścia 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`

Może być użyty do wyodrębnienia wartości z dowolnego json:

value=`echo "$jsondata"|grep -w \"key_name\" |tail -1 | cut -d\" -f4
 2
Author: Ehsan Chavoshi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-19 13:20:02