Чтение данных JSON в сценарии оболочки

В оболочке у меня есть требование, в котором я должен прочитать ответ JSON, который находится в следующем формате:

 { "Messages": [ { "Body": "172.16.1.42|/home/480/1234/5-12-2013/1234.toSort", "ReceiptHandle": "uUk89DYFzt1VAHtMW2iz0VSiDcGHY+H6WtTgcTSgBiFbpFUg5lythf+wQdWluzCoBziie8BiS2GFQVoRjQQfOx3R5jUASxDz7SmoCI5bNPJkWqU8ola+OYBIYNuCP1fYweKl1BOFUF+o2g7xLSIEkrdvLDAhYvHzfPb4QNgOSuN1JGG1GcZehvW3Q/9jq3vjYVIFz3Ho7blCUuWYhGFrpsBn5HWoRYE5VF5Bxc/zO6dPT0n4wRAd3hUEqF3WWeTMlWyTJp1KoMyX7Z8IXH4hKURGjdBQ0PwlSDF2cBYkBUA=", "MD5OfBody": "53e90dc3fa8afa3452c671080569642e", "MessageId": "e93e9238-f9f8-4bf4-bf5b-9a0cae8a0ebc" } ] }

Здесь меня интересует только свойство свойства Body. Я сделал несколько неудачных попыток:

 jsawk -a 'return this.Body' 

или

 awk -v k="Body" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]} 

Но этого было недостаточно. Может ли кто-нибудь помочь мне с этим?

Ответ 1

Для разбора json в командной строке jq:

 jq '.Body'

Посетите это для jq: https://stedolan.github.io/jq/

Ответ 2

TL;DR

$ cat /tmp/so.json | underscore select '.Messages .Body' 
["172.16.1.42|/home/480/1234/5-12-2013/1234.toSort"]

Инструменты консоли Javascript

Вы можете использовать инструменты Javascript CLI, например

Пример

Выберите всех name дочерних элементов addons:

underscore select ".addons > .name"

underscore-cli предоставляют другие примеры реального мира, а также json: select() doc.

Ответ 3

Аналогичным образом используется Bash regexp. Удалите любую пару ключ/значение.

key="Body"
re="\"($key)\": \"([^\"]*)\""

while read -r l; do
    if [[ $l =~ $re ]]; then
        name="${BASH_REMATCH[1]}"
        value="${BASH_REMATCH[2]}"
        echo "$name=$value"
    else
        echo "No match"
    fi
done

Регулярное выражение может быть настроено на соответствие нескольким пробелам/вкладкам или символам новой строки. Не работает, если значение имеет встроенный ". Это иллюстрация. Лучше использовать некоторый "промышленный" парсер:)

Ответ 4

Вот грубый способ сделать это: преобразовать JSON в переменные bash для их eval.

Это работает только для:

  • JSON, который не содержит вложенных массивов, и
  • JSON из надежных источников (иначе это может запутать ваш сценарий оболочки, возможно, он даже может нанести вред вашей системе, вы были предупреждены)

Ну, да, он использует PERL для выполнения этой работы, благодаря CPAN, но достаточно мал для включения непосредственно в сценарий и, следовательно, быстро и легко отлаживается:

json2bash() {
perl -MJSON -0777 -n -E 'sub J {
my ($p,$v) = @_; my $r = ref $v;
if ($r eq "HASH") { J("${p}_$_", $v->{$_}) for keys %$v; }
elsif ($r eq "ARRAY") { $n = 0; J("$p"."[".$n++."]", $_) foreach @$v; }
else { $v =~ '"s/'/'\\\\''/g"'; $p =~ s/^([^[]*)\[([0-9]*)\](.+)$/$1$3\[$2\]/;
$p =~ tr/-/_/; $p =~ tr/A-Za-z0-9_[]//cd; say "$p='\''$v'\'';"; }
}; J("json", decode_json($_));'
}

используйте его как eval "$(json2bash <<<'{"a":["b","c"]}')"

Не сильно проверено, хотя. Обновления, предупреждения и другие примеры смотрите в моем GIST.

Обновить

(К сожалению, ниже приведено решение только для ссылок, так как код C слишком длинный, чтобы его здесь дублировать.)

Для всех тех, кому не нравится вышеупомянутое решение, теперь есть программа на C json2sh, которая (надеюсь, безопасно) преобразует JSON в переменные оболочки. В отличие от фрагмента perl, он способен обрабатывать любой JSON, если он правильно сформирован.

Предостережения:

  • json2sh не был проверен много.
  • json2sh может создавать переменные, которые начинаются с шаблона shellshock () {

Я написал json2sh для возможности .bson Shell:

bson2json()
{
printf '[';
{ bsondump "$1"; echo "\"END$?\""; } | sed '/^{/s/$/,/';
echo ']';
};

bsons2json()
{
printf '{';
c='';
for a;
do
  printf '%s"%q":' "$c" "$a";
  c=',';
  bson2json "$a";
done;
echo '}';
};

bsons2json */*.bson | json2sh | ..

Разъяснение:

  • bson2json .bson файл .bson так, что записи становятся массивом JSON
    • Если все работает хорошо, применяется END0 -Marker, иначе вы увидите что-то вроде END1.
    • END -Marker необходим, иначе пустые файлы .bson не будут отображаться.
  • bsons2json выгружает кучу файлов .bson как объект, где выходные данные bson2json индексируются по имени файла.

Затем он json2sh, так что вы можете использовать grep/source/eval/etc. что нужно, чтобы принести значения в оболочку.

Таким образом, вы можете быстро обработать содержимое дампа MongoDB на уровне оболочки, без необходимости сначала импортировать его в MongoDB.