0

I have a json file that looks like this:

{"data":{"players":[{"id":"aaaa","is_multiple":false,"name":"TV Woonkamer","password_protected":false,"support_seek":false,"support_set_volume":false,"type":"upnp"},{"id":"bbbb","is_multiple":false,"name":"squeezelite","password_protected":false,"support_seek":true,"support_set_volume":true,"type":"upnp"},{"id":"cccc","is_multiple":false,"name":"Woonkamer","password_protected":false,"support_seek":true,"support_set_volume":true,"type":"airplay"},{"id":"__dddd__","is_multiple":true,"name":"Multiple AirPlay Devices","password_protected":false,"support_seek":true,"support_set_volume":true,"type":"airplay"}]},"success":true}

Parsed by PHP:

stdClass Object
(
[data] => stdClass Object
    (
        [players] => Array
            (
                [0] => stdClass Object
                    (
                        [id] => uuid:aaaa
                        [is_multiple] => 
                        [name] => TV Woonkamer
                        [password_protected] => 
                        [support_seek] => 
                        [support_set_volume] => 
                        [type] => upnp
                    )

                [1] => stdClass Object
                    (
                        [id] => uuid:bbbb
                        [is_multiple] => 
                        [name] => squeezelite
                        [password_protected] => 
                        [support_seek] => 1
                        [support_set_volume] => 1
                        [type] => upnp
                    )

                [2] => stdClass Object
                    (
                        [id] => cccc
                        [is_multiple] => 
                        [name] => Woonkamer
                        [password_protected] => 
                        [support_seek] => 1
                        [support_set_volume] => 1
                        [type] => airplay
                    )

                [3] => stdClass Object
                    (
                        [id] => __dddd__
                        [is_multiple] => 1
                        [name] => Multiple AirPlay Devices
                        [password_protected] => 
                        [support_seek] => 1
                        [support_set_volume] => 1
                        [type] => airplay
                    )

            )

    )

[success] => 1
)

I would like to loop through it from a linux command line and found all IDs of players where is_multiple is empty and type is airplay. The following shows a list of all players with type is airplay, but how do I start a loop?

jq '.data .players[]' scan.json | jq 'select(.type=="airplay")' | jq -r '.id'
6
  • 2
    That is not JSON at all! It looks like PHP's variable dump (If I recall correctly). Commented Jun 18, 2018 at 6:10
  • My bad, you're correct this is what it looks liked when parsing it with PHP. Commented Jun 18, 2018 at 6:36
  • I guess you want to call a command for each of the ids..? Try eg | xargs -I{} command {}. (btw the jq commands can be piped inside the jq language - like < scan.json jq -r '.data .players[]|select(.type=="airplay")|.id'. Commented Jun 18, 2018 at 8:43
  • @liborm help, I'm quit new to this. Do you have a complete example for me? Commented Jun 18, 2018 at 8:50
  • You need to be more specific about what your 'loop' is supposed to do. Commented Jun 18, 2018 at 8:52

2 Answers 2

1

I believe the code you're after is something like

<scan.json jq -r '.data.players[]|select(.type == "airplay" and .is_multiple == false)|.id' |
   xargs -I{} wget -q "https://my.web/?id={}"

If the operation with each id is more complex, you can wrap it either in a .sh script, or in a bash function (like process_one_id(){ commands.. ;}.

NB: to use a bash function with xargs you have to do export -f process_one_id and then call it through bash like xargs -I {} bash -c process_one_id {}. Or use GNU parallel which makes it transparent to call exported shell functions.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, that indeed shows the list I'm looking for, but would you mind explaining me how to use it so I can use the output (ID) as a variable? E.g. calling a wget using the ID?
The {} string is your 'variable' in the xargs call. Updated the answer accordingly.
Seeing adding the commands inline will create a very long command (I'm running several commands for each ID), I was hoping on using a function so I created a simple "function test() { }", but I can't seem to find out how to call that function. Simply adding test after -I{} results in xargs: test: No such file or directory
Ah, sorry, my bad. Calling a bash function from xargs is a little more complicated. You can either use the trick mentioned here or use GNU parallel instead of xargs, which will make the if more transparent.
0

I solved it as followed:

jq -r '.data.players[]|select(.type == "airplay" and .is_multiple == false)|.id' players.json | while read i; do
    # i is the id of the player
    echo $i
done

Thanks @liborm for helping me on my way!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.