Using jq with bash to run command for each object in array

前端 未结 5 1499
眼角桃花
眼角桃花 2021-02-02 07:48

How can I run a Bash command for every JSON object in a JSON array using jq? So far I have this:

cat credentials.json | jq -r \'.[] | .user, .date, .         


        
相关标签:
5条回答
  • 2021-02-02 08:23

    Your best bet is probably to output each record in something like TSV format, then read that from a shell loop.

    jq -r '.[]|[.user, .date, .email] | @tsv' |
      while IFS=$'\t' read -r user date email; do
        mycommand -u "$user" -d "$date" -e "$email"
      done
    

    jq itself doesn't have anything like a system call to run an external command from within a filter, although it seems that they are working on it.

    0 讨论(0)
  • 2021-02-02 08:30

    You could have jq output the commands to execute, something like

    .[] | "mycommand \(.user|@sh) \(.date|@sh) \(.email|@sh)"
    

    Then execute it. Something like

    bash <(jq -r '.[] | "mycommand \(.user|@sh) \(.date|@sh) \(.email|@sh)"' foo)
    
    0 讨论(0)
  • 2021-02-02 08:30

    With xargs:

    curl localhost:8082/connectors | jq .[] | xargs -L1 -I'{}' curl -XDELETE 'localhost:8082/connectors/{}' 
    

    Or equivalently, to show the output of that first curl:

    echo '["quickstart-file-sink4","quickstart-file-source","quickstart-file-sink","quickstart-file-sink2","quickstart-file-sink3","quickstart-file-source2"]' | jq .[] | xargs -L1 -I'{}' curl -XDELETE 'localhost:8082/connectors/{}' 
    

    jq .[] strips off one level of containment, so that a list becomes output as one line per item.

    xargs -L1 processes one line at a time

    xargs -I'{}' specifies that the string {} be replaced with the input line when invoking the following command.

    xargs is essentially a map operator for the shell.

    0 讨论(0)
  • 2021-02-02 08:31

    Here is another variation which I based on the answer from @chepner.

    echo "$config" | jq -c '.[]' |
    while IFS=$"\n" read -r c; do
        echo "start"
        host=$(echo "$c" | jq -r '.host')
        echo $host
        echo "end"
    done
    

    I used jq's -c option to output "compact" jsons, so they are all on one line.

    In combination with IFS=$"\n", I was able to loop over each item in the input json's array and do what I wanted to do.

    So, with an input of

    [
     {
      "host": "host1",
      "settings": {}
     },
     {
      "host": "host1",
      "settings": {}
     }
    ]
    

    the output is

    start
    host1
    end
    start
    host2
    end
    
    0 讨论(0)
  • 2021-02-02 08:44

    I came across the same problem recently where xargs doesn't help that much due to the relatively complicated set of arguments I wanted to pass around. Thus I implemented an sh filter (and its friends) to jq. I haven't yet had enough time to write documentation and tests for it so not creating a PR for it to become a part of the official codebase yet. So now it's only for the ones who are willing to compile this version themselves:

    https://github.com/haochenx/jq/tree/sh-support

    0 讨论(0)
提交回复
热议问题