Bash Jq анализирует строку json

Я должен вызвать файл и передать json в качестве параметров таким образом (предположим, что мой файл называется test.sh), из bash мне нужно сделать что-то вроде этого:

./test.sh "[{\"username\":\"user1\",\"password\":\"pwd1\",\"group\":\"usergroup1\"},{\"username\":\"user2\",\"password\":\"pwd2\",\"group\":\"usergroup2\"},{\"username\":\"user3\",\"password\":\"pwd3\",\"group\":\"usergroup3\"}]"

и содержимое test.sh следующее

#!/bin/bash

#read the json
system_user="$1"

printf "$system_user"

accounts=($(jq -s ".[]" <<< $system_user))

printf "$accounts"

for account in "${accounts[@]}"
do
  printf "\n\n$account\n\n"
done 

вывод -> printf "$ system_user"

[{"username":"user1","password":"pwd1","group":"usergroup1"},{"username":"user2","password":"pwd2","group":"usergroup2"},{"username":"user3","password":"pwd3","group":"usergroup3"}]

но вывод -> printf "$accounts" примерно такой

[
[
{
"username":
"user1"
и т. д. и т. д. и т. д. один объект для каждого токена :-(

и так далее, но я ожидал массив из трех объектов (например, вы можете протестировать на jqplay.org)

 {
   "username": "user1",
   "password": "pwd1",
   "group": "usergroup1"
 }
 {
   "username": "user2",
   "password": "pwd2",
   "group": "usergroup2"
 }
 {
   "username": "user3",
   "password": "pwd3",
   "group": "usergroup3"
 }

Таким образом я могу сделать foreach для ${accounts[@]}

Что я делаю неправильно? Спасибо


person user2548436    schedule 20.07.2016    source источник
comment
jq '.[]' <<< "..." (без -s) дает вам желаемый результат; вы можете подумать, почему вы думаете, что вам нужен массив bash для хранения этого в первую очередь. В зависимости от того, что вы хотите делать с данными, вы можете сделать это непосредственно в jq.   -  person chepner    schedule 20.07.2016


Ответы (2)


С параметром -c вы можете печатать каждый объект JSON в одной строке, что упрощает заполнение нужного массива.

$ readarray -t arr < <(jq -c '.[]' <<< "[{\"username\":\"user1\",\"password\":\"pwd1\",\"group\":\"usergroup1\"},{\"username\":\"user2\",\"password\":\"pwd2\",\"group\":\"usergroup2\"},{\"username\":\"user3\",\"password\":\"pwd3\",\"group\":\"usergroup3\"}]") 
$ printf "Object: %s\n" "${arr[@]}"
Object: {"username":"user1","password":"pwd1","group":"usergroup1"}
Object: {"username":"user2","password":"pwd2","group":"usergroup2"}
Object: {"username":"user3","password":"pwd3","group":"usergroup3"}
person chepner    schedule 20.07.2016

Вы меняете местами массивы bash и массивы JSON. Когда вы создаете массив accounts, bash разбивает элементы на каждый пробел. Вот почему вы не получаете того, что ожидаете. Вы можете попробовать следующее:

declare -A accounts

while IFS="=" read -r key value
do
    accounts[$key]="$value"
done < <(jq -r "to_entries|map(\"\(.key)=\(.value)\")|.[]" <<< $system_user)

for account in "${accounts[@]}"
do
    printf "$account\n"
done

(украдено отсюда: https://stackoverflow.com/a/26717401/328977)

чтобы получить следующий вывод:

{"username":"user1","password":"pwd1","group":"usergroup1"}
{"username":"user2","password":"pwd2","group":"usergroup2"}
{"username":"user3","password":"pwd3","group":"usergroup3"}
person buff    schedule 20.07.2016