Синтаксический анализ JSON с помощью инструментов Unix
Я пытаюсь разобрать JSON, возвращенный из запроса curl, например:
curl 'http://twitter.com/users/username.json' |
sed -e 's/[{}]/''/g' |
awk -v k="text" '{n=split(,a,","); for (i=1; i<=n; i++) print a[i]}'
выше разбивает JSON на поля, например:
% ...
"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
% ...
как напечатать определенное поле (обозначается -v k=text
)?
30 ответов
существует ряд инструментов, специально разработанных для манипулирования JSON из командной строки, и будет намного проще и надежнее, чем делать это с Awk, например jq
:
curl -s 'https://api.github.com/users/lambda' | jq -r '.name'
вы также можете сделать это с помощью инструментов, которые, вероятно, уже установлены в вашей системе, как Python с помощью json
модуль, и поэтому избегайте любых дополнительных зависимостей, все еще имея преимущество правильного парсера JSON. Следующий предположим, вы хотите использовать UTF-8, в котором исходный JSON должен быть закодирован, и это то, что используют большинство современных терминалов:
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'])"
Исторические заметки
этот ответ первоначально рекомендуется jsawk, который все равно должен работать, но немного более громоздкий в использовании, чем jq
и зависит от установленного автономного интерпретатора JavaScript, который менее распространен, чем Python переводчик, поэтому приведенные выше ответы, вероятно, предпочтительнее:
curl -s 'https://api.github.com/users/lambda' | jsawk -a 'return this.name'
этот ответ также первоначально использовал API Twitter из вопроса, но этот API больше не работает, что затрудняет копирование примеров для тестирования, а новый API Twitter требует ключей API, поэтому я переключился на использование API GitHub, который можно легко использовать без ключей API. Первым ответом на первоначальный вопрос будет:
curl 'http://twitter.com/users/username.json' | jq -r '.text'
чтобы быстро извлечь значения для определенного ключа, мне лично нравится использовать "grep-o", который возвращает только совпадение регулярного выражения. Например, чтобы получить поле "текст" из твитов, что-то вроде:
grep -Po '"text":.*?[^\]",' tweets.json
это регулярное выражение более надежное, чем вы могли бы подумать; например, оно отлично справляется со строками, имеющими встроенные запятые и экранированные кавычки внутри них. Я думаю, что с немного большей работой вы могли бы сделать тот, который действительно гарантированно извлекает значение, если он атомарный. (Если это имеет вложенность, тогда regex не может этого сделать, конечно.)
и для дальнейшей очистки (хотя и сохраняя исходное экранирование строки) вы можете использовать что-то вроде: | perl -pe 's/"text"://; s/^"//; s/",$//'
. (Я сделал это для этот анализ.)
для всех ненавистников, которые настаивают, что вы должны использовать настоящий парсер JSON - да, это важно для корректности, но
- чтобы сделать действительно быстрый анализ, как подсчет значений для проверки на данных очистки ошибки или получить общее чувство для данные, строчит что-то в командной строке быстрее. Открытие редактора для написания сценария отвлекает.
-
grep -o
на порядок быстрее, чем стандарт Pythonjson
библиотека, по крайней мере, при этом для твитов (которые составляют ~2 КБ каждый). Я не уверен, что это просто потому, чтоjson
медленно (я должен когда-нибудь сравнить с yajl); но в принципе, регулярное выражение должно быть быстрее, поскольку оно конечное состояние и гораздо более оптимизируемо, а не парсер, который должен поддерживать рекурсия, и в этом случае тратит много деревьев построения ЦП для структур, о которых вы не заботитесь. (Если бы кто-то написал преобразователь конечного состояния, который сделал правильный (ограниченный глубиной) анализ JSON, это было бы фантастически! А пока у нас есть"grep-o".)
чтобы написать поддерживаемый код, я всегда использую настоящую библиотеку синтаксического анализа. Я не пробовал!--26-->jsawk, но если он работает хорошо, это будет адресовать точку №1.
последнее, более дурацкое решение: я написал скрипт, использующий Python json
и извлекает ключи, которые вы хотите, в столбцы, разделенные вкладками; затем я пропускаю через обертку вокруг awk
что позволяет им получить доступ к столбцам. здесь: сценарии json2tsv и tsvawk. Так что для этого примера это будет:
json2tsv id text < tweets.json | tsvawk '{print "tweet " $id " is: " $text}'
этот подход не касается #2, более неэффективен, чем один скрипт Python, и он немного хрупкий: он заставляет нормализацию новых строк и вкладок в строковых значениях, чтобы хорошо играть с awk поле / запись-разделенный вид мира. Но это позволяет вам оставаться в командной строке с большей корректностью, чем grep -o
.
на основании того, что некоторые из рекомендаций здесь (esp в комментариях) предложили использовать Python, я был разочарован, не найдя примера.
Итак, вот одна строка, чтобы получить одно значение из некоторых данных JSON. Предполагается, что вы передаете данные (откуда-то) и поэтому должны быть полезны в контексте сценариев.
echo '{"hostname":"test","domainname":"example.com"}' | python -c 'import json,sys;obj=json.load(sys.stdin);print obj[0]["hostname"]'
следующим MartinR и Boecko ведущий:
$ curl -s 'http://twitter.com/users/username.json' | python -mjson.tool
то передаст вам весьма выход grep содружественный. Очень удобно:
$ curl -s 'http://twitter.com/users/username.json' | python -mjson.tool | grep my_key
вы могли бы просто скачать jq
binary для вашей платформы и (chmod +x jq
):
$ curl 'https://twitter.com/users/username.json' | ./jq -r '.name'
он извлекает "name"
атрибут из объекта json.
jq
Домашняя страница говорит, что это нравится sed
для данных JSON.
использовать поддержка JSON Python вместо использования awk!
что-то вроде этого:
curl -s http://twitter.com/users/username.json | \
python -c "import json,sys;obj=json.load(sys.stdin);print obj['name'];"
Через Узел.js
если система имеет узел установлен, можно использовать -p
печать -e
evaulate флаги сценария с JSON.parse
вытащить любое значение, которое требуется.
простой пример использования строки JSON { "foo": "bar" }
и вытаскивая значение "foo":
$ node -pe 'JSON.parse(process.argv[1]).foo' '{ "foo": "bar" }'
bar
потому что у нас есть доступ к cat
и другие утилиты, мы можем использовать эти файлы:
$ node -pe 'JSON.parse(process.argv[1]).foo' "$(cat foobar.json)"
bar
или любой другой формат, например URL-адрес, содержащий JSON:
$ node -pe 'JSON.parse(process.argv[1]).name' "$(curl -s https://api.github.com/users/trevorsenior)"
Trevor Senior
ты спросил, как стрелять себе в ногу и я здесь, чтобы обеспечить боеприпасы:
curl -s 'http://twitter.com/users/username.json' | sed -e 's/[{}]/''/g' | awk -v RS=',"' -F: '/^text/ {print }'
вы могли бы использовать tr -d '{}'
вместо sed
. Но их полное отсутствие, похоже, также имеет желаемый эффект.
если вы хотите снять внешние кавычки, передайте результат выше через sed 's/\(^"\|"$\)//g'
Я думаю, что другие прозвучали достаточно тревоги. Я буду ждать с мобильником, чтобы вызвать скорую. Стреляйте, когда будете готовы.
использование Bash с Python
создайте функцию bash в вашем .файл bash_rc
function getJsonVal () {
python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)))";
}
затем
$ curl 'http://twitter.com/users/username.json' | getJsonVal "['text']"
My status
$
здесь та же функция, но с проверкой ошибок.
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)))";
}
где $ # - ne 1 гарантирует, что по крайней мере 1 вход, и-T 0 убедитесь, что вы перенаправляете из трубы.
хорошая вещь об этой реализации заключается в том, что вы можете получить доступ к вложенным значениям json и получить JSON взамен! =)
пример:
$ echo '{"foo": {"bar": "baz", "a": [1,2,3]}}' | getJsonVal "['foo']['a'][1]"
2
если вы хотите быть действительно фантазии, вы можете довольно распечатать данные:
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"
}
разбор JSON с помощью PHP CLI
возможно, не по теме, но поскольку приоритет царит, этот вопрос остается неполным без упоминания нашего надежного и верного PHP, я прав?
используя тот же пример JSON, но позволяет назначить его переменной, чтобы уменьшить неясность.
$ export JSON='{"hostname":"test","domainname":"example.com"}'
теперь для PHP goodness, используя функции file_get_contents и php: / / stdin обертки потока.
$ echo $JSON|php -r 'echo json_decode(file_get_contents("php://stdin"))->hostname;'
или как указано, используя fgets и уже открытый поток на константе CLI STDIN.
$ echo $JSON|php -r 'echo json_decode(fgets(STDIN))->hostname;'
кафе!
TickTick - парсер JSON, написанный на bash (
вот отрывок автора из его статьи,представьте себе мир, где Bash поддерживает 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
собственная версия Bash: Также хорошо работает с обратными косыми чертами ( \ ) и кавычками (")
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
версия, которая использует Ruby и http://flori.github.com/json/
$ < file.json ruby -e "require 'rubygems'; require 'json'; puts JSON.pretty_generate(JSON[STDIN.read]);"
или более лаконично:
$ < file.json ruby -r rubygems -r json -e "puts JSON.pretty_generate(JSON[STDIN.read]);"
можно использовать jshon
:
curl 'http://twitter.com/users/username.json' | jshon -e text
к сожалению, верхний проголосовал ответ, который использует grep
возвращает полное матч, который не работал в моем сценарии, но если вы знаете, что формат JSON останется постоянным, вы можете использовать lookbehind и lookahead извлечь только нужные значения.
# 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
вот один из способов сделать это с 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
}
}
}'
кто-то, у кого также есть xml-файлы, может захотеть посмотреть на мой Xidel. Это cli, свободный от зависимостей JSONiq процессор. (т. е. он также поддерживает XQuery для обработки xml или json)
примером в вопросе будет:
xidel -e 'json("http://twitter.com/users/username.json")("name")'
или с моим собственным нестандартным синтаксисом расширения:
xidel -e 'json("http://twitter.com/users/username.json").name'
для более сложного анализа JSON я предлагаю использовать модуль python jsonpath (от Stefan Goessner) -
- установите его -
sudo easy_install-U jsonpath
- использовать его -
пример файла.json (от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
}
}
}
разберите его (извлеките все названия книг с ценой
$ cat file.json | python -c "import sys, json, jsonpath; print '\n'.join(jsonpath.jsonpath(json.load(sys.stdin), 'store.book[?(@.price < 10)].title'))"
выход -
Sayings of the Century
Moby Dick
Примечание: выше командной строки не включает проверку ошибок. для полного решения с проверкой ошибок вы должны создать небольшой скрипт python и обернуть код с помощью try-except.
если у вас php:
php -r 'var_export(json_decode(`curl http://twitter.com/users/username.json`, 1));'
например:
у нас есть ресурс, который предоставляет json с кодами iso стран:http://country.io/iso3.json и мы можем легко увидеть его в оболочке с завитком:
curl http://country.io/iso3.json
но это выглядит не очень удобно, и не читается, лучше разбирать json и видеть читаемую структуру:
php -r 'var_export(json_decode(`curl http://country.io/iso3.json`, 1));'
этот код будет печатать что-то вроде:
array (
'BD' => 'BGD',
'BE' => 'BEL',
'BF' => 'BFA',
'BG' => 'BGR',
'BA' => 'BIH',
'BB' => 'BRB',
'WF' => 'WLF',
'BL' => 'BLM',
...
если у вас есть вложенные массивы этого выход будет выглядеть намного лучше...
надеюсь, это будет полезно...
вы можете попробовать что-то вроде этого -
curl -s 'http://twitter.com/users/jaypalsingh.json' |
awk -F=":" -v RS="," '~/"text"/ {print}'
разбор JSON болезнен в сценарии оболочки. С более подходящим языком создайте инструмент, который извлекает атрибуты JSON в соответствии с соглашениями сценариев оболочки. Новый инструмент можно использовать для решения непосредственной проблемы сценариев оболочки, а затем добавить его в комплект для будущих ситуаций.
например, рассмотрим инструмент jsonlookup такое, что если я говорю jsonlookup access token id
он вернет атрибут id определено в атрибуте маркер определено в атрибуте открыть из stdin, который предположительно является данными JSON. Если атрибут не существует, инструмент ничего не возвращает (состояние выхода 1). В случае сбоя синтаксического анализа выйдите из состояния 2 и отправьте сообщение в stderr. Если поиск выполняется успешно, инструмент печатает значение атрибута.
создав инструмент unix для точного извлечения значений JSON, вы можете легко использовать его в сценариях оболочки:
access_token=$(curl <some horrible crap> | jsonlookup access token id)
любой язык будет делать для реализации jsonlookup. Вот довольно краткая версия python:
#!/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
двухстрочный, который использует python. Особенно хорошо это работает, если вы пишете сингл .sh file, и вы не хотите зависеть от другого .файл py. Он также использует использование pipe |
. echo "{\"field\": \"value\"}"
может быть заменен чем угодно, печатающим json в stdout.
echo "{\"field\": \"value\"}" | python -c 'import sys, json
print(json.load(sys.stdin)["field"])'
Это хороший usecase для pythonpy:
curl 'http://twitter.com/users/username.json' | py 'json.load(sys.stdin)["name"]'
Если pip
доступен в системе после:
$ pip install json-query
примеры использования:
$ 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
теперь, когда Powershell является кросс-платформенной, я подумал, что я бы бросил свой путь туда, так как я нахожу его довольно интуитивным и чрезвычайно простым.
curl -s 'https://api.github.com/users/lambda' | ConvertFrom-Json
ConvertFrom-Json преобразует JSON в пользовательский объект Powershell,поэтому вы можете легко работать со свойствами с этого момента. Если вам нужно только свойство "id", например, вы просто сделаете это:
curl -s 'https://api.github.com/users/lambda' | ConvertFrom-Json | select -ExpandProperty id
если вы хотите вызвать все это из Bash, тогда вам придется назвать это вот так:
powershell 'curl -s "https://api.github.com/users/lambda" | ConvertFrom-Json'
конечно, есть чистый способ Powershell сделать это без завитка, который был бы:
Invoke-WebRequest 'https://api.github.com/users/lambda' | select -ExpandProperty Content | ConvertFrom-Json
наконец, есть также "ConvertTo-Json", который преобразует пользовательский объект в JSON так же легко. Вот пример:
(New-Object PsObject -Property @{ Name = "Tester"; SomeList = @('one','two','three')}) | ConvertTo-Json
который произвел бы хороший JSON, как это:
{
"Name": "Tester",
"SomeList": [
"one",
"two",
"three"
]
}
по общему признанию, использование оболочки Windows в Unix несколько кощунственно, но Powershell действительно хорош в некоторых вещах и разборе JSON и XML-это несколько из них. Эту страницу GitHub для платформы версии https://github.com/PowerShell/PowerShell
это еще один bash
& python
гибридный ответ. Я опубликовал этот ответ, потому что хотел обработать более сложный вывод JSON, но, уменьшая сложность моего приложения bash. Я хочу взломать следующий объект JSON из http://www.arcgis.com/sharing/rest/info?f=json в bash
:
{
"owningSystemUrl": "http://www.arcgis.com",
"authInfo": {
"tokenServicesUrl": "https://www.arcgis.com/sharing/rest/generateToken",
"isTokenBasedSecurity": true
}
}
в то время как этот подход увеличивает сложность функции Python, использование bash становится проще:
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
выход выше скрипт:
- {"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
I добавлена поддержка массивов, поэтому вы можете использовать .length
и, если исходный массив строк, вы можете использовать .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
выходы:
- 1
- [{"данные": 591657527.591555, "разрешение": 156543.03392800014, "уровень": 0}, {"данные": 295828763.795777, "разрешение": 78271.51696399994, "уровня": 1}, {"Данные": 147914381.897889, "разрешение": 39135.75848200009, "Уровень": 2}, {"Данные": 73957190.948944, "разрешение": 19567.87924099992, "Уровень": 3}, {"данные": 36978595.474472, "разрешение": 9783.93962049996, "Уровень": 4}, {"данные": 18489297.737236, "разрешение": 4891.96981024998, "Уровень": 5}, {"данные": 9244648.868618, "разрешение": 2445.98490512499, "Уровень": 6}, {"данные": 4622324.434309, "разрешение": 1222.992452562495, "Уровень": 7}, {"данные": 2311162.217155, "разрешение": 611.4962262813797, "Уровень": 8}, {"данные": 1155581.108577, "разрешение": 305.74811314055756, "Уровень": 9}, {"данные": 577790.554289, "разрешение": 152.87405657041106, "уровень": 10}, {"масштаб": 288895.277144, "разрешение": 76.43702828507324, "Уровень": 11}, {"масштаб": 144447.638572, "разрешение": 38.21851414253662, "Уровень": 12}, {"масштаб": 72223.819286, "разрешение": 19.10925707126831, "Уровень": 13}, {"масштаб": 36111.909643, "разрешение": 9.554628535634155, "уровень": 14}, {"масштаб": 18055.954822, "разрешение": 4.77731426794937, "уровень": 15}, {"масштаб": 9027.977411, "разрешение": 2.388657133974685," уровень": 16}, {"масштаб": 4513.988705, "разрешение": 1.1943285668550503, "уровень": 17}, {"масштаб": 2256.994353, "разрешение": 0.5971642835598172, "уровень": 18}, {"масштаб": 1128.497176, "разрешение": 0.29858214164761665, "уровень": 19}, {"масштаб": 564.248588, "разрешение": 0.14929107082380833, "уровень": 20}, {"масштаб": 282.124294, "разрешение": 0.07464553541190416, "уровень": 21}, {"масштаб": 141.062147, "разрешение": 0.03732276770595208, "Уровень": 22}, {"масштаб": 70.5310735, "разрешение": 0.01866138385297604," уровень": 23}]
- 24
- {"масштаб": 70.5310735, "разрешение": 0.01866138385297604, "уровень": 23}
Если кто-то просто хочет извлечь значения из простых объектов JSON без необходимости вложенных структур, можно использовать регулярные выражения, даже не выходя из bash.
вот функция, которую я определил с помощью регулярных выражений bash на основе стандарт 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
}
предостережения: объекты и массивы не поддерживаются как значения, но поддерживаются все другие типы значений, определенные в стандарте. Кроме того, пара будет соответствовать независимо от того, как глубоко в документе JSON, если он имеет точно такое же имя ключа.
используя пример 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
вот хорошая ссылка. В этом случае:
curl 'http://twitter.com/users/username.json' | sed -e 's/[{}]/''/g' | awk -v k="text" '{n=split(,a,","); for (i=1; i<=n; i++) { where = match(a[i], /\"text\"/); if(where) {print a[i]} } }'
Ниет это инструмент, который поможет вам извлечь данные из файла JSON или yaml непосредственно в вашей оболочке/bash CLI.
$ pip install niet
рассмотрим файл json с именем project.JSON со следующим содержанием:
{
project: {
meta: {
name: project-sample
}
}
вы можете использовать niet так:
$ PROJECT_NAME=$(niet project.json project.meta.name)
$ echo ${PROJECT_NAME}
project-sample
я использовал это для извлечения длительности видео из вывода 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`
его можно использовать для извлечения значения из любого json:
value=`echo "$jsondata"|grep -w \"key_name\" |tail -1 | cut -d\" -f4