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
)?
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'
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
- 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.
-
{[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, żejson
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
.
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"]'
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
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.
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'];"
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
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'
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"
}
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!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
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]
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]);"
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
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 grep
zwraca 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
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
}
}
}'
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'
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)-
- Install it -
Sudo easy_install-U jsonpath
- 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.
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...
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}'
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
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"])'
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"]'
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
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
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:
- {"owningSystemUrl": "http://www.arcgis.com", "authInfo": {"tokenServicesUrl": " https://www.arcgis.com/sharing/rest/generateToken", "isTokenBasedSecurity": true}}
- {"tokenServicesUrl": "https://www.arcgis.com/sharing/rest/generateToken", "isTokenBasedSecurity": true}
- https://www.arcgis.com/sharing/rest/generateToken
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}
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
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]} } }'
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
$ 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
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
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