Парсинг JSON с помощью инструментов Unix
Я пытаюсь разобрать JSON, возвращаемый из запроса curl, вот так:
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]}'
В результате я получаю разбивку 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
?
5 ответ(ов)
На основе того, что некоторые рекомендации здесь (особенно в комментариях) предложили использовать Python, я был разочарован, что не нашел примера.
Вот однострочник, который позволяет получить одно значение из JSON-данных. Он предполагает, что вы передаете данные через конвейер (откуда-то), и поэтому будет полезен в контексте скриптов.
echo '{"hostname":"test","domainname":"example.com"}' | python -c 'import json,sys;obj=json.load(sys.stdin);print(obj["hostname"])'
Обратите внимание, что для Python 3 необходимо использовать print()
с круглыми скобками.
Не удалось получить ответ от AI: пустой ответ
Использование Bash с Python
Создайте функцию Bash в файле *.bashrc*
:
function getJsonVal () {
python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)$1))";
}
После этого вы можете использовать следующую команду:
curl 'http://twitter.com/users/username.json' | getJsonVal "['text']"
Вывод будет следующим:
My status
Вот аналогичная функция, но с проверкой на ошибки:
function getJsonVal() {
if [ \( $# -ne 1 \) -o \( -t 0 \) ]; then
cat <<EOF
Использование: getJsonVal 'ключ' < /tmp/
-- или --
cat /tmp/input | getJsonVal 'ключ'
EOF
return;
fi;
python -c "import json,sys;sys.stdout.write(json.dumps(json.load(sys.stdin)$1))";
}
Где #$ -ne 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)$1, sort_keys=True, indent=4))";
}
echo '{"foo": {"bar": "baz", "a": [1,2,3]}}' | getJsonVal "['foo']"
Вывод:
{
"a": [
1,
2,
3
],
"bar": "baz"
}
К сожалению, самый голосуемый ответ, который использует grep
, возвращает полное совпадение, что не сработало в моем случае. Однако, если вы знаете, что формат JSON останется неизменным, вы можете использовать lookbehind и lookahead для извлечения только нужных значений.
# Получаем значение "FooBar"
echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="FooBar":")(.*?)(?=",)'
# Вывод: he\"llo
# Получаем значение "TotalPages"
echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="TotalPages":)(.*?)(?=,)'
# Вывод: 33
# Получаем значение "anotherValue"
echo '{"TotalPages":33,"FooBar":"he\"llo","anotherValue":100}' | grep -Po '(?<="anotherValue":)(.*?)(?=})'
# Вывод: 100
Таким образом, с помощью указанных регулярных выражений вы можете получать только необходимые значения из вашего JSON.
Для того чтобы красиво отформатировать JSON-файл с использованием Ruby и библиотеки JSON, вы можете воспользоваться следующей командой:
< file.json ruby -e "require 'rubygems'; require 'json'; puts JSON.pretty_generate(JSON[STDIN.read]);"
Эта команда читает содержимое файла file.json
, анализирует его как JSON и выводит его в читаемом формате.
Можно сделать этот процесс более лаконичным, используя короткие флаги для импорта библиотек:
< file.json ruby -r rubygems -r json -e "puts JSON.pretty_generate(JSON[STDIN.read]);"
Эта второй вариант делает то же самое, но немного компактнее. Выбирайте любой из способов в зависимости от ваших предпочтений!
Безопасное преобразование строки JSON в объект
Почему Python не может разобрать эти данные JSON? [закрыто]
Как разобрать JSON в Java
Как сравнить массивы в JavaScript?
Как работает "cat << EOF" в bash?