12

Парсинг JSON с помощью инструментов Unix

11

Я пытаюсь разобрать 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 ответ(ов)

1

На основе того, что некоторые рекомендации здесь (особенно в комментариях) предложили использовать Python, я был разочарован, что не нашел примера.

Вот однострочник, который позволяет получить одно значение из JSON-данных. Он предполагает, что вы передаете данные через конвейер (откуда-то), и поэтому будет полезен в контексте скриптов.

echo '{"hostname":"test","domainname":"example.com"}' | python -c 'import json,sys;obj=json.load(sys.stdin);print(obj["hostname"])'

Обратите внимание, что для Python 3 необходимо использовать print() с круглыми скобками.

0

Не удалось получить ответ от AI: пустой ответ

0

Использование 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"
}
0

К сожалению, самый голосуемый ответ, который использует 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.

0

Для того чтобы красиво отформатировать 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]);"

Эта второй вариант делает то же самое, но немного компактнее. Выбирайте любой из способов в зависимости от ваших предпочтений!

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь